程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言進階【宏定義】編譯預處理#define

C語言進階【宏定義】編譯預處理#define

編輯:關於C語言

C語言學習筆記

之  編譯預處理與宏定義

  宏是編譯預處理的重要定義,宏定義就像基本數據類型定義一樣,可以看作是一種類型,與基本類型不同的是,宏與函數有著密切的相似之處,但是宏是編譯時發生作用。

一:不帶參數的宏定義

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved