之 編譯預處理與宏定義
宏是編譯預處理的重要定義,宏定義就像基本數據類型定義一樣,可以看作是一種類型,與基本類型不同的是,宏與函數有著密切的相似之處,但是宏是編譯時發生作用。
1. 一般格式:
#define 標識符 字符串 標識符即為這個字符串的宏名
2. 宏調用:程序中用宏名代替字符串。
宏展開:預編譯時將字符串代替宏名的過程。
比如:#define PI 3.14
這裡的PI就是宏名,他代表的是字符串3.14,預編譯時將源程序中的所有宏名PI出現的位置都用字符串3.14來替換。比如: 程序中出現PI*5,它的結果實際上是 3.14*5
1)宏名用大寫,用來區分普通變量
2)宏定義不能以分號結束,否則分號將作為字符串的一部分參加宏展開。比如:
#define PI 3.1415; //結尾加了分號
a=PI*r*r;
在編譯預處理時,將宏展開: a=3.1415;*r*r 分號將作為字符串參加運算,很明顯是錯誤的
3)宏定義只是用來替換字符串的。 不管字符串是什麼數據類型,總之就是一句話,宏名替換字符串,宏名替換的一定是字符串,即使上述中的3.1415寫成了3.1W15。替換後的結果依然是a=3.1W15*r*r。
4)#define命令定義的宏名范圍是從定義命令開始直到源程序文件結束,而且#define定義在文件開頭與函數之間。 如果要想提前結束宏定義的作用域,可以通過#undef終止宏名的作用域
5)宏定義中可以出現已經定義的宏名,可以層層置換。
若宏名中 出現一個被雙引號括起來的字符串中時,將不會產生宏替換。
比如:
#include <stdio.h> /*宏定義在文件頭和函數之間*/ #define R 3.0 #define PI 3.1415926 #define L 2*PI*R //出現了前面已經定義的PI和R #define S PI*R*R //出現了前面已經定義的PI和 main() { /* 當L和S在“”之內時將不會與宏定義產生聯系,即不會發生替換 當L和S不在“”之內時,L將被替換成 2*PI*R,S將被替換成 PI*R*R */ printf("L=%7.2f\nS=%7.2f\n",L,S); }
最後需要注意的是: 宏定義是專用於預處理的一個名詞,它的作用就是替換,不分配空間
一般格式:
#define 宏名參數表) 字符串
帶參數的宏定義並不僅僅是宏名代換字符串,還要進行參數的替換,類似於函數的調用
比如:
#define S(a,b) a*b
area=S(3,2);
S為宏名,a和b為形參,程序中調用S3,2),把實參3和2分別替換形參a和b,所以宏展開是area=3*2;
比如:
#include <stdio.h> /*宏定義在文件頭和函數之間*/ #define S(a,b) a*b //需要注意的是S和()之間不能有空格 main() { int area; area=S(2,3);//傳遞給宏S(a,b),然後替換為a*b printf("area=%d\n",area); }
1)上述程序中的參數傳遞應該很好理解,但是如果把程序改動一下,讓實參的值變成S(2+3,3+4), 大家肯定會認為是35,但是真的是35嗎? 我們看一下:
#include <stdio.h> /*宏定義在文件頭和函數之間*/ #define S(a,b) a*b //需要注意的是S和()之間不能有空格 main() { int area; area=S(2+3,3+4); printf("area=%d\n",area); }
竟然是15,並不是我們想象中的35,怎麼回事呢? 實際上S(2+3,3+4)傳遞過去後,它的紅替換是 area=2+3*3+4,這下大家明白了吧。還是一句話,宏定義只是用來替換的,完完全全的原樣的替換。那要怎麼解決這個問題呢?很簡單,在宏定義的時候加上一個括號就可以了,看程序:
#include <stdio.h> /*宏定義在文件頭和函數之間*/ #define S(a,b) (a)*(b) //需要注意的是S和()之間不能有空格 main() { int area; area=S(2+3,3+4);//傳遞給宏S(a,b),然後替換為a*b printf("area=%d\n",area); }
(2)宏定義的宏調用與函數調用的區別
在學習了帶參數的宏定義後,是不是覺得這個調用與函數的調用很相似,但是它們完全是不通的兩個概念:
函數調用時,先求出實參表達式的值,再將該值傳遞個形參,而帶參數的宏調用只是進行替換,簡單的字符替換
函數調用是在程序運行時處理,分配給形參臨時內存單元,而宏展開則在編譯時進行的,展開的時並不給形參分配內存單元,不進行值傳遞,也沒有返回值
本文出自 “趙玉強的博客” 博客,請務必保留此出處http://zhaoyuqiang.blog.51cto.com/6328846/1266617