C语言:随笔7--预处理命令
以#開頭的就是預處理命令。
#include<stdio.h>//標準的輸入輸出頭文件
#define PI 3.1415925//宏定義命令
在源程序中這些命令都是放在函數之外,而且一般都是放在源文件的前面,他們稱為預處理部分。(因為他們比源文件更早的被處理到)
一、無參數的宏定義
1、無參數的宏名后不帶參數。
其定義的一般形式為:
#define 標識符 字符串//其中“#”表示這是一條預處理命令
凡是以“#”開頭的均為預處理命令。define為宏定義命令。”標識符“為多定義的宏名。“字符串”可以是闡述、表達式、格式串等。
//例如
#define PI 3.1415926
//他的作用是指定標識符PI來代替數3.1415926.
//在百你寫源程序時,所有的3.1415926都可以由PI代替,而對源程序做編譯時,將由預處理程序進行宏代換,即用3.1415926表達式去置換所有的宏名PI,然后再進行編譯。
不帶參數的宏定義說明:
(1)宏定義是用宏名來表示一個字符串,再宏展開時又以該字符串取代宏名,這只是一種簡單的替換,字符串可以是含任何字符,可以是常數,也可以是表達式,預處理程序時對他不做任何檢查,如有錯誤,只能在編譯已被宏展開后的源程序時發現。
(2)宏定義不是說明或者語句,在行末不必加分號,如加上分號則連分號也一起置換。
(3)宏定義必須寫在函數之外,其作用域為宏定義命令起到源程序結束。如要終止其作用域可使用#undef命令。#undef 標識符
(4)宏名在源程序中若用引號括起來,則預處理程序不對其作宏代換。(用雙引號括起來的我們都把他當作常量字符串是要輸出出來的)
(5)宏定義允許嵌套,在宏定義的字符串中可以使用已經定義的宏名。在宏展開式由預處理程序層層替換。
(6)習慣上宏名用大寫字母表示,以便于與變量區別。但也允許用小寫字母。(因為習慣上規定變量名用小寫)
(7)可用宏定義表示數據類型,使書寫方便。?
比如:#define TNTEGER int(用TNTEGER a;就表示int a;)
-----PS:宏定義表示數據類型和用typedef定義數據說明符的區別
區別:宏定義只是簡單的字符串替換,是在預處理完成的,而typedef(其實是個語句,后面有分號“;”)是在編譯時處理的,他不是作簡單的替換,而是對類型說明符重新命名。被命名的標識符具有類型定義說明的功能。
用以下實例作比較:
#include<stdio.h>
#define PTN1 char*//PIN1是一個char* 是一個指針形式的字符
typedef char* PIN2;//指針形式的字符為PIN2
void main()
{PIN1 x,y;//用PIN1定義x和y//3宏定義替換:char* x,y;(相當于定義x是一個指針而y是一個字符型)PIN2 a,b;//用PIN2定義a和b//4而用typedef呢使類型重命名,將char*用PIN2表示,也就是說這里相當于char* a,char* b;所以打印出來不一樣printf("By #define:%d %d\n\n",sizeof(x),sizeof(y));//分別取他們的大小然后打印。1打印結果4 1printf("By typedef:%d %d\n\n",sizeof(a),sizeof(b)); //2打印結果:4 4}
(8)對“輸出格式”作宏定義,可以減少書寫麻煩。(比如在輸出時用printf打印需要%d、%s一百遍較麻煩)
#include<stdio.h>
#define P printf
#define D "%d\n"
#define F "%f\n"void main()
{int a=5,c=8,e=11;float b=3.8,d=9.7,f=21.08;P(D F,a,b);P(D F,c,d);P(D F,e,f);}
二、帶參數的宏定義
C語言允許宏帶有參數,在宏定義中的參數稱為形式參數,在宏調用中的參數稱為實際參數。
對帶參數的宏,在調用中,不僅要宏展開,而且要用實參去替換形參。
帶參宏定義的一般形式為:
#define 宏名(形參表) 字符串//不帶分號“;”
帶參宏調用的一般形式為:
宏名(實參表);//帶分號“;”
例如:
#define M(y) y*y+3*y//宏定義//參數是y,字符串是y*y+3*y
...
K=M(5);//宏調用//傳遞給的實參是5,在調用時,實參5去替換形參y。(但是這里跟函數的調用值傳遞是不一樣的,這里是直接的替換)
實例:
#include<stdio.h>
#define MAX(a,b) (a>b?a:b)//a和b是虛有的只是一個替代的符號
void main()
{int x,y,max;//定義了類型printf("input two numbers:")scanf("%d %d",&x,&y);max=MAX(x,y);//這里替換為max=(x>y)?x,y;//上邊的a和b就被x和y實參化了printf("The max is %d\n\n",max);}
帶參數的宏定義說明:
(1)帶參宏定義中,宏名和形參表之間不能有空格出現。比如上邊就不能寫為#define MAX ? (a,b)之間不能有空格。
(2)在帶參宏定義中,形式參數不分配內存單元,因此不必做類型定義。而宏調用中的實參有具體的值。要用他的去代替形參,因此必須做類型說明。(這是與函數中的情況不同。在函數中形參和實參是兩個不同的量,各有自己的作用域,(也就是說函數中定義中形參有他的變量值,實參有他的變量值)調用時要把實參值賦予形參,進行“值傳遞”。而在帶參宏中只是符號替換,不存在值傳遞的問題。)(在宏中只有實參有他的作用范圍)
(3)在定義宏中的形參是標識符,而宏調用中的實參可以是表達式。(何為表達式呢其實就是一個式子)
#include<stdio.h>
#define SAY(y) (y)
void main()
{int i;char say[]={73,32,108,111,118,101,32,102,105,115,104,99,46,99,111,109,3}while(say[i]){say[i]=SAY(say[i]+1);//可以是表達式(剛才打印的各個字符的ASCII碼加1)}printf("\n\t%s\n\n",say);//打印出來I love fishc,com!
}
#include<stdio.h>
#define SAY(y) (y)^(y)//里邊的符號^是異或的意思
void main()
{int i;char say[]={73,32,108,111,118,101,32,102,105,115,104,99,46,99,111,109,3}while(say[i]){say[i]=SAY(say[i]^say[i]);}printf("\n\t%s\n\n",say);}
(4)在宏定義中,字符串內的形參通常要用括號括起來以避免出錯。(加括號避免優先級發生改變)
(5)帶宏的參和帶參數的函數很相似,但有本質上的不同,除上面已談到的各點外,把同一表達式用函數處理與用宏處理兩者的結果有可能是不同的。
三、條件編譯
預處理程序提供了條件編譯功能。可以按不同的條件去編譯不同的程序部分,因而產生不同的目標代碼文件。這對于程序的移植和調試是很有用的。
條件編譯有三種潛規則:
第一種:功能是:如果標識符已被#define命令定義過則對程序段1進行編譯;否則對程序段2進行編譯。
#ifdef 標識符//如果有定義這個標識符的話,那么就執行程序1程序段1
#else//沒有定義的話就執行2程序段2
#endif
?如果沒有程序段2(他為空)本格式中的#else可以沒有,即可以寫為:
#ifdef 標識符//如果有定義這個標識符的話,那么就執行程序程序段
#endif
第二種形式:
#ifndef 標識符//如果沒有定義這個標識符的話,那么就執行程序1程序段1
#else//有定義的話就執行2程序段2
#endif
第三種形式:
#if 常量表達式//if 0下邊的就不會被編譯執行做注釋用的多(相當于一個開關,是1就執行程序1,是0就執行程序2)程序段1
#else程序段2
#endif
?
總結
以上是生活随笔為你收集整理的C语言:随笔7--预处理命令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Papers with Code
- 下一篇: C语言:随笔8--结构体