Linux C语言结构体
前面學習了c語言的基本語法特性,本節進行更深入的學習。
預處理程序。 編譯指令: 預處理, 宏定義,
建立自己的數據類型:結構體,聯合體,動態數據結構
c語言表達式工具 邏輯運算符:?& | ^ ~ << >>
函數的遞歸調用方法
什么是預處理
vim?helloworld.c1helloworld.c:
#include?int?main() {????printf("hello,world!\n");????return?0; }1234567編譯的目的:
從c語言.c源文件變成可執行文件
gcc?helloworld.c?-o?helloworld.out./helloworld.out12編譯的四個步驟:
.c文件->.i文件->.s文件->.o文件->可執行文件(可運行)
下面我們來查看預處理中要做的事情:
gcc?-o?helloworld.i?helloworld.c?-E1-E表示只讓gcc執行預處理。
//?查看helloworld.i文件cat?helloworld.i12vim跳到整個文檔底部,命令:?:$
可以看到代碼的底端是我們的main函數
對比一下.i文件和.c文件的區別
首先:它們都是c的語法。其次.c文件main函數上面是#include
而.i?文件中這行代碼不見了,變成了上面這些東西。
所以預處理所做的第一件事情就是展開頭文件
將#include 中stdio.h展開,將未注釋的內容直接寫入.i文件。
在預處理步驟中,除了展開頭文件,還要進行宏替換。
宏是什么
c語言常量分為直接常量和符號常量:
#define?標識符?常量值?(注意:沒有分號)1helloMacro.c源代碼:
#include?#define?R?10int?main() {????int?a?=R;????printf("a=%d\n");????printf("hello,world!\n");????return?0; }12345678910gcc?-o?helloMacro.i?helloMacro.c?-E1預處理過之后的代碼
#?4?"helloworld.c"int?main() {????int?a?=10;????printf("a=%d\n");????printf("hello,world!\n");????return?0; }12345678可以看到10是直接當做一個字符串來替換原本的宏定義R。
宏的本質是發生在預處理階段單純的字符串替換(宏替換), 在預處理階段,宏不考慮語法;
示例代碼2:
vim helloMacro2.c
預處理是沒有問題的,可以成功的編譯執行。宏不考慮C語言的語法。它很單純,字符串替換。
宏用于大量反復使用的常量、數組buffer的大小,為了便于修改定義成宏。
通常定義數組我們這樣寫:
int?a[10];int?b[10];12定義兩個相同大小的數組,這里我們就可以改為下面代碼。
#define?R?10int?a[R];int?b[R];123一次修改,可以修改兩份。
宏也是可以傳遞參數的,可以做一些函數可以做的事情
宏函數
vim helloMacroFunction.c
源代碼:
這里的處理過程: 首先將參數a替換到上面的宏中,上面就變成了N(a) a*10,之后再用a*10替換下面的N(a)
int?b?=?N(a);?//變成了?int?b?=a*10;1gcc?-o?helloMacroFunction.i?helloMacroFunction.c?-E1預處理之后:
#?8?"hello.c"int?main(){????int?a?=?10;????int?b?=a*10;????printf("b?=?%d\n",b);????printf("a?=%d\n",a);????printf("hello,world!\n");????return?0; }123456789先不考慮宏實現,先來寫一個正常的求和函數。
vim?helloAdd.c1#include?#define?R?20#define?M?int?main(#define?N(n)?n*10int?add(int?a,int?b){????return?a b; }M){????int?a?=?R;????printf("a?=%d\n",a);????printf("hello,world!\n");????int?b?=N(a);????printf("b?=?%d\n",b);????int?c?=add(a,b);????printf("c?=%d\n",c);????return?0; }1234567891011121314151617181920212223gcc?helloAdd.c?-o?helloAdd.out./helloAdd.out12使用宏函數實現求和。
vim?helloAddMacro.c1#include?#define?R?20#define?M?int?main(#define?N(n)?n*10#define?ADD(a,b)?a bint?add(int?a,int?b){????return?a b; }M){????int?a?=?R;????printf("a?=%d\n",a);????printf("hello,world!\n");????int?b?=N(a);????printf("b?=?%d\n",b);????int?c?=add(a,b);????printf("c?=%d\n",c);????int?d?=ADD(a,b);????printf("d?=%d\n",d);????return?0; }1234567891011121314151617181920212223242526gcc?helloAddMacro.c?-o?helloAddMacro.out./helloAddMacro.out12可以看到使用宏函數和普通函數的求和效果是一致的。結果與簡單的字符串替換一致。
ADD(a,b)?被替換成?a b?因此式子變成int d = a b;
gcc?-o?helloAddMacro.i?helloAddMacro.c?-E vim?helloAddMacro.i12版本3,宏定義中優先級問題。
#include?#define?R?20#define?M?int?main(#define?N(n)?n*10#define?ADD(a,b)?a bint?add(int?a,int?b){????return?a b; }M){????int?a?=?R;????printf("a?=%d\n",a);????printf("hello,world!\n");????int?b?=N(a);????printf("b?=?%d\n",b);????int?c?=add(a,b);????printf("c?=%d\n",c);????int?d?=ADD(a,b);????printf("d?=%d\n",d);????int?e?=ADD(a,b)?*?ADD(a,b);????printf("e?=%d\n",e);????return?0; }1234567891011121314151617181920212223242526272829預測一下e的輸出為:?a b*a b?ab先乘起來,a=20,b=200,ab=4000,然后加上a,b:得到結果(4220)
gcc?helloAddMacroPrecedence.c?-o?helloAddMacroPrecedence.out./helloAddMacroPrecedence.out12運算是等我們編譯完了,執行的時候才會運行的。預處理階段不會進行運算操作。
宏定義時由于本質是字符串的替換
真正運算的時候,會按照運算符號的優先級來進行
解決方案:
#define?ADD(a,b)?(a b)1gcc?helloAddMacroPrecedence.c?-o?helloAddMacroPrecedence2.out./helloAddMacroPrecedence2.out12加個括號,保證優先級更高一點。
宏函數和正常函數的優勢?
正常的add函數需要返回值類型,需要傳遞進來的參數有類型要求。
講傳入的a,b 類型進行改變,如變為兩個浮點型數,程序就會自動類型轉換。
但是宏函數就沒有這種要求可以不用考慮輸入值的類型,這與普通的函數定義不同。
int?c?=add(10.5,20.4);printf("c?=%d\n",c);float?d?=ADD(10.5,20.4);printf("d?=%f\n",d);12345gcc?helloAddMacroPrecedenceCompare.c?-o?helloAddMacroPrecedenceCompare.out./helloAddMacroPrecedenceCompare.out12普通函數例如int add(int a,int b)除了在開頭要聲明值的類型,還要設置返回值,因此在定義過程與調用過程相對復雜。若能用宏定義實現的情況應優先考慮宏定義.
宏是不考慮數據類型,不考慮c語言的語法的。只是簡單的字符串的處理。
預處理階段,除了宏之外,還提供了一個叫做mtianyan:條件編譯的功能。
可以按照不同的條件,編譯不同的程序部分,從而產生不同的目標代碼文件。對于程序的移植和調試都是很有用的。
下集預告: 和宏比較相近的功能,typedef
Linux C預處理之typedef
嚴格來講,typedef和預處理是沒
總結
以上是生活随笔為你收集整理的Linux C语言结构体的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 半智能手机是什么意思
- 下一篇: 电脑百度云下载加速器(百度云加速器电脑版