define的用法小結
define的用法只是一種純粹的替換功能,宏定義的替換是預處理器處理的替換。
一:簡單的宏定義用法
格式:#define 標識符 替換內容
替換的內容可以是數字,字符,字符串,特殊字符和空格,後面是什麼內容就會替換成什麼內容。
例如:
#define N 5 效果等同於 int array [5];
int array[N];
同樣效果:
#define N = 5
int array[N]; 效果等同於 int array[= 5];
同樣效果:
#define N 5;
int array[N]; 效果等同於 int array[5;];
常見的一種錯誤:
#define pin int*
pin a , b ; 實際上的效果是 int *a , b;
#define N 2+2
void main(void)
{
int a = N * N;
printf("%d\n" , a );
}
結果是2+2*2+2=8
二:帶參數的宏定義的使用
例子說話:一個求正方形面積的函數
使用#define的正確寫法應該是:
#include<stdio.h>
#define area(x) ((x)*(x))
int main(void)
{
int s = area(3 + 3);
printf("s = %d\n" , s);
return 0;
}
運行結果:(3+3)*(3+3)= 36 是我們想要的結果
常見問題寫成:
#include<stdio.h>
#define area(x) x*x
int main(void)
{
int s = area(3 + 3);
printf("s = %d\n" , s);
return 0;
}
運行結果:3 + 3 * 3 + 3 = 15 不是我們想要的結果
這更能體現出前面說的define的宏定義就是純粹的一種替換,做的是先替換後計算的工作。
防止這種問題的方法:
要想能夠真正使用好宏定義,防止出現上面一二兩種常用情況的一些錯誤,一定要記住在思路上先將程序中對宏的使用全部替換成它所代表的字符串,不要自作主張地添加任何其他符號,完全展開後再進行相應的計算,就不會寫錯運行結果。在編程使用宏替換時,當字符串中不只一個符號時,加上括號表現出優先級,如果是帶參數的宏定義,則要給宏體中的每個參數加上括號,並在整個宏體上再加一個括號。
三:常用作對函數的封裝
例子說話:現在原有一個求兩個數乘積的函數mult
[Linux@centos-64-min exercise]$ cat mul.c
#include <stdio.h>
int mult(int x , int y )
{
int result = x * y;
return result;
}
現在需要不同的兩個功能函數,一個是求正方形面積的函數 square_area和一個求長方形的面積的函數rectangle_area。
可以這樣寫:
[Linux@centos-64-min exercise]$ cat mul.c
#include <stdio.h>
int mult(int x , int y )
{
int result = x * y;
return result;
}
[Linux@centos-64-min exercise]$ cat try.c
#include <stdio.h>
int mult(int x , int y); /*兩個數字相乘的函數的聲明*/
#define square_area(str , x) mult(x , x) /*封裝成一個求正方形面積的函數*/
#define rectangle_area(str , x , y) mult(x , y) /*封裝成一個求長方形面積的函數*/
/*上面那些函數聲明和宏定義按照比較規范的書寫,本來應該放在一個頭文件裡面的,這裡為了說明問題就簡單放在函數裡了*/
int main(void)
{
int s = 0;
s = square_area("This is the area of the square" , 3);
printf("This is the area of the square : s = %d\n" , s);
s = rectangle_area("This is the area of the rectangle" , 3 ,4);
printf("This is the area of the rectangle : s = %d\n" , s);
return 0;
}
運行結果:
[Linux@centos-64-min exercise]$ gcc -o try try.c mul.o
[Linux@centos-64-min exercise]$ ./try
This is the area of the square : s = 9
This is the area of the rectangle : s = 12
四:define中的三個特殊符號:#,##,#@
#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x
x##y表示x連接y,舉例說:
int n = Conn(123,456); 結果就是n=123456;
char* str = Conn("asdf", "adf")結果就是 str = "asdfadf";
#@x,其實就是給x加上單引號,結果返回是一個const char。舉例說:
char a = ToChar(1);結果就是a='1';
做個越界試驗char a = ToChar(123);結果就錯了;
但是如果你的參數超過四個字符,編譯器就給給你報錯了!error C2015: too many characters in constant :P
#x,表示給x加雙引號
char* str = ToString(123132);就成了str="123132";
五:小結#define宏定義
(1) 方便程序的修改
使用簡單宏定義可用宏代替一個在程序中經常使用的常量,這樣在將該常量改變時,不用對整個程序進行修改,只修改宏定義的字符串即可,而且當常量比較長時, 我們可以用較短的有意義的標識符來寫程序,這樣更方便一些。
(2) 宏定義是在預編譯的時候就進行替換。程序中調用子函數執行完之後都必須飯後調用該子函數的現場繼續往下執行,這樣就會出現了函數轉換的消耗。但是使用帶參數的宏定義就不會出現這個問題,因為它是在預處理階段即進行了宏展開,在執行時不需要轉換,即在當地執行,但復雜的操作還是要由函數調用來完成,而且宏定義所占用的目標代碼空間相對較大。所以在使用時要依據具體情況來決定是否使用宏定義。