<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] # 基本概念 c語言對源程序處理的四個步驟:預處理,編譯,匯編,鏈接 預處理是在程序源代碼被編譯之前,由預處理器(Preprocessor)對程序源代碼進行的處理.這個過程并不對程序的源代碼語法進行解析,但它會把源代碼分割或處理成為特定的符號為下一步的編譯做準備工作 # 文件包含指令 文件包含處理是指一個源文件可以將另外一個文件的全部內容包含進來.c語言提供了`#include`命令用來實現"文件包含"的操作 ![](https://box.kancloud.cn/5f03c0347d40a290ac6d805306e1bad3_724x312.png) ## `#include<>`和`#include ""`區別 * ""表示系統先在file1.c所在的當前目錄找file1.h,如果找不到,再按系統指定的目錄檢索 * `<>`表示系統直接按系統指定的目錄檢索 注意: 1. `#include<>`常用于包含庫函數的頭文件 2. `#include ""`常用于包含自定義的頭文件 3. 理論上`#include`可以包含任意格式的文件(`.c .h`等),但一般用于頭文件的包含 # 宏參數的字符串化 `#` 的用法 **#用來將宏參數轉換為字符串**,也就是在宏參數的開頭和末尾添加引號。例如有如下宏定義: `#define STR(s) #s` 那么: ~~~ printf("%s", STR(c.biancheng.net)); printf("%s", STR("c.biancheng.net")); ~~~ 分別被展開為: ~~~ printf("%s", "c.biancheng.net"); printf("%s", "\"c.biancheng.net\""); ~~~ 可以發現,即使給宏參數“傳遞”的數據中包含引號,使用#仍然會在兩頭添加新的引號,而原來的引號會被轉義。 將上面的例子補充完整: ~~~ #include <stdio.h> #define STR(s) #s int main() { printf("%s\n", STR(c.biancheng.net)); printf("%s\n", STR("c.biancheng.net")); return 0; } 運行結果: c.biancheng.net "c.biancheng.net" ~~~ 注意: 對空格處理 當傳入參數名間存在空格時,編譯器將會自動連接各個子字符串,用每個子字符串中只以一個空格連接,忽略其中多余一個的空格 ~~~ printf("%s\n", STR(abc 123)); ~~~ 輸出 ~~~ abc 123 ~~~ # 宏參數的連接 `##`的用法 `##`稱為連接符,用來將宏參數或其他的串連接起來。例如有如下的宏定義: ~~~ #define CON1(a, b) a##e##b #define CON2(a, b) a##b##00 ~~~ 那么: ~~~ printf("%f\n", CON1(8.5, 2)); printf("%d\n", CON2(12, 34)); ~~~ 將被展開為: ~~~ printf("%f\n", 8.5e2); printf("%d\n", 123400); ~~~ 將上面的例子補充完整: ~~~ #include <stdio.h>#define CON1(a, b) a##e##b#define CON2(a, b) a##b##00int main() { printf("%f\n", CON1(8.5, 2)); printf("%d\n", CON2(12, 34)); return 0;} ~~~ 運行結果: ~~~ 850.000000 123400 ~~~ 注意: 當用`##`連接形參時,`##`前后的空格可有可無 另外,如果`##`后的參數本身也是一個宏的話,`##`會阻止這個宏的展開 # 宏定義 ## 無參數的宏定義(宏常量) 如果在程序中大量用到了100這個值,那么為了方便管理,我們可以將其定義為: `const int num = 100;` 但是如果我們使用num定義一個數組,在不支持c99標準的編譯器上是不支持的,因為num不是一個編譯器常量,如果想得到一個編譯器常量,那么可以使用: ~~~ #define num 100 ~~~ 在編譯預處理時,將程序中在該語句以后出現的所有的num都用100代替.這種寫法使用戶能以一個簡單的名字代替一個長的字符串,在預處理時將宏名替換成字符串的過程稱為**宏展開**.宏定義,只在宏定義的文件中起作用 說明: 1. 宏名一般用于大寫,以便于與變量區別 2. 宏定義可以是常數,表達式等 3. 宏定義不作語法檢查,只有在編譯被宏展開后的源程序才會報錯 4. 宏定義不是c語言,不在行末加分號 5. 宏名有效范圍為從定義到本源文件結束 6. 可以用`#undef`命令終止宏定義的作用域 ## 帶參數的宏定義(宏函數) 在項目中,經常把一些短小又頻繁使用的函數寫成宏函數,這是由于宏函數沒有普通函數參數壓棧,跳轉,返回等開銷,可以調高程序的效率 宏通過使用參數,可以創建外形和作用都與函數類似的類函數宏(function-like macro) 宏的參數也用園括號括起來 ~~~ #define SUM(x, y) ((x) + (y)) void test() { //僅僅只是做文本替換,下邊替換為int ret = ((10) + (20)); //不進行計算 int ret = SUM(10, 20); printf("ret:%d\n", ret); } ~~~ 注意: 1. 宏的名字中不能有空格,但是在替換的字符串中可以有空格.ANSIC允許在參數列表中使用空格 2. 用括號括住每一個參數,并括住宏的整體定義 3. 用大寫字母表示宏的函數名 4. 如果打算宏代替函數來加快程序運行速度.假如在程序中只使用一次宏對程序的運行時間沒有太大提高 # 一些特殊的預定義宏 c編譯器,提供了幾個特定形式的預定義宏,在實際編程中可以直接使用,很方便 ~~~ //__FILE__ 宏所在文件的源文件名 //__LINE__ 宏所在行的行號 //__DATE__ 代碼編譯的日期 //__TIME__ 代碼編譯的時間 int main() { printf("%s\n", __FILE__); printf("%d\n", __LINE__); printf("%s\n", __DATE__); printf("%s\n", __TIME__); getchar(); return 0; } ~~~ 輸出 ~~~ /Users/jdxia/Desktop/study/studyc/main.c 7 Oct 19 2019 22:35:14 ~~~ # 條件編譯 一般情況下,源程序中所有的行都參加編譯.但是有時希望對部分源程序行只在滿足一定條件下才編譯,即對這部分源程序行指定編譯條件 ~~~ //#define FLAG #define FLAG #ifdef FLAG void func(long a) { } #else void func(int a) { } #endif ~~~ ![](https://box.kancloud.cn/302ee46a51c50bbf21d8e4cc986e1642_685x234.png) ## `#if`的用法 ~~~ #include <stdio.h> int main(){ #if _WIN32 printf("This is Windows!\n"); #else printf("Unknown platform!\n"); #endif #if __linux__ printf("This is Linux!\n"); #endif return 0; } ~~~ ## `#ifdef` 的用法 #ifdef 用法的一般格式為: ~~~ #ifdef ?宏名 ? ? 程序段1 #else ? ? 程序段2 #endif ~~~ 它的意思是,如果當前的宏已被定義過,則對“程序段1”進行編譯,否則對“程序段2”進行編譯。 也可以省略 `#else`: ~~~ #ifdef ?宏名 ? ? 程序段 #endif ~~~ VS/VC 有兩種編譯模式,Debug 和 Release。在學習過程中,我們通常使用 Debug 模式,這樣便于程序的調試;而最終發布的程序,要使用 Release 模式,這樣編譯器會進行很多優化,提高程序運行效率,刪除冗余信息。 為了能夠清楚地看到當前程序的編譯模式,我們不妨在程序中增加提示,請看下面的代碼: ~~~ #include <stdio.h> #include <stdlib.h> int main(){ #ifdef _DEBUG printf("正在使用 Debug 模式編譯程序...\n"); #else printf("正在使用 Release 模式編譯程序...\n"); #endif system("pause"); return 0; } ~~~ 當以 Debug 模式編譯程序時,宏 \_DEBUG 會被定義,預處器會保留第 5 行代碼,刪除第 7 行代碼。反之會刪除第 5 行,保留第 7 行 ## `#ifndef`的用法 `#ifndef` 用法的一般格式為: ~~~ #ifndef 宏名 ? ? 程序段1? #else? ? ? 程序段2? #endif ~~~ 與 `#ifdef` 相比,僅僅是將 `#ifdef`?改為了 `#ifndef`。它的意思是,如果當前的宏未被定義,則對“程序段1”進行編譯,否則對“程序段2”進行編譯,這與 `#ifdef` 的功能正好相反。 ## 三者之間的區別 最后需要注意的是,#if 后面跟的是“整型常量表達式”,而 #ifdef 和 #ifndef 后面跟的只能是一個宏名,不能是其他的。 例如,下面的形式只能用于 #if: ~~~ #include <stdio.h> #define NUM 10 int main(){ #if NUM == 10 || NUM == 20 printf("NUM: %d\n", NUM); #else printf("NUM Error\n"); #endif return 0; } ~~~ 運行結果: NUM: 10 再如,兩個宏都存在時編譯代碼A,否則編譯代碼B: ~~~ #include <stdio.h> #define NUM1 10 #define NUM2 20 int main(){ #if (defined NUM1 && defined NUM2) //代碼A printf("NUM1: %d, NUM2: %d\n", NUM1, NUM2); #else //代碼B printf("Error\n"); #endif return 0; } ~~~ 運行結果: NUM1: 10, NUM2: 20 `#ifdef` 可以認為是 `#if defined` 的縮寫 # `#error`命令 #error 指令用于在編譯期間產生錯誤信息,并阻止程序的編譯,其形式如下: ~~~ #error error_message ~~~ 例如,我們的程序針對 Linux 編寫,不保證兼容 Windows,那么可以這樣做: ~~~ #ifdef WIN32 #error This programme cannot compile at Windows Platform #endif ~~~ WIN32 是 Windows 下的預定義宏。當用戶在 Windows 下編譯該程序時,由于定義了 WIN32 這個宏,所以會執行?`#error?`命令,提示用戶發生了編譯錯誤,錯誤信息是: ~~~ This programme cannot compile at Windows Platform ~~~ 這和發生語法錯誤的效果是一樣的,程序編譯失敗。請看下面的截圖: ![](https://box.kancloud.cn/45ac33fefca77be28bad3134b393774b_847x159.png) 需要注意的是:報錯信息不需要加引號`" "`,如果加上,引號會被一起輸出。例如將上面的 #error 命令改為: ~~~ #error "This programme cannot compile at Windows Platform" ~~~ 那么錯誤信息如下: ![](https://box.kancloud.cn/d1f360116a2f857810a2e15087d26a4b_768x221.png) 再如,當我們希望以 C++ 的方式來編譯程序時,可以這樣做: ~~~ #ifndef __cplusplus #error 當前程序必須以C++方式編譯 #endif ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看