亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

C語(yǔ)言

C語(yǔ)言#define的用法

時(shí)間:2024-08-19 19:01:20 C語(yǔ)言 我要投稿
  • 相關(guān)推薦

C語(yǔ)言#define的用法

  引導(dǎo)語(yǔ):預(yù)處理器是在真正的編譯開始之前由編譯器調(diào)用的獨(dú)立程序。以下是百分網(wǎng)小編分享給大家的C語(yǔ)言#define的用法,歡迎閱讀!

  #define的用法

  #define 是一個(gè)預(yù)處理指令,這個(gè)預(yù)處理執(zhí)行可以定義宏。與所有預(yù)處理指令一樣,預(yù)處理指令#define用#符號(hào)作為行的開頭。預(yù)處理指令從#開始,到其后第一個(gè)換行符為止。也就是說(shuō),指令的長(zhǎng)度限于一行代碼。如果想把指令擴(kuò)展到幾個(gè)物理行,可使用反斜線后緊跟換行符的方法實(shí)現(xiàn),該出的換行符代表按下回車鍵在源代碼文件中新起一行所產(chǎn)生的字符,而不是符號(hào) \n 代表的字符。在預(yù)處理開始錢,系統(tǒng)會(huì)刪除反斜線和換行符的組合,從而達(dá)到把指令擴(kuò)展到幾個(gè)物理行的效果。可以使用標(biāo)準(zhǔn)C注釋方法在#define行中進(jìn)行注釋。

  //使用反斜線+回車

  #define OW "hello\

  world!" /*注意第二行要左對(duì)齊*/

  每一個(gè)#define行由三部分組成:

  第一部分,指令#deine自身。

  第二部分,所選擇的縮略語(yǔ),這些縮略語(yǔ)稱為宏(分為對(duì)象宏和函數(shù)宏)。宏的名字中不允許有空格,而且必須遵循C變量命名規(guī)則:只能使用字母、數(shù)字和下劃線(_),第一個(gè)字符不能為數(shù)字。習(xí)慣上宏名用大寫字母表示,以便于與變量區(qū)別。但也允許用小寫字母。

  第三部分,(#define行的其余部分)稱為替換列表或主體。

  注意,結(jié)尾沒(méi)有分號(hào)

  下面來(lái)看一個(gè)例子:

  #include

  #define OW 2 * 2

  #define OW 2 * 2

  //#undef OW 需要先取消宏定義

  #define OW 2*2

  int main (void)

  {

  printf ("%d\n", OW);

  return 0;

  }

  輸出結(jié)果:

  define.c:5:0: 警告: “OW”重定義 [默認(rèn)啟用]

  define.c:4:0: 附注: 這是先前定義的位置

  相同定義意味著主體具有相同順序的語(yǔ)言符號(hào)。因此,下面兩個(gè)定義相同:

  #define OW 2 * 2

  #define OW 2 * 2

  兩者都有三個(gè)相同的語(yǔ)言符號(hào),而且額外的空格不是主體的一部分。下面的定義則被認(rèn)為是不同的:

  #define OW 2*2

  上式只有一個(gè)(而非三個(gè))語(yǔ)言符號(hào),因此與前面兩個(gè)定義不同?梢允褂#undef指令重新定義宏。

  宏所代表的數(shù)字可以在編譯命令中指定(使用-D選項(xiàng))

  /*

  宏演示

  */

  #include

  int main()

  {

  int num=0;

  int arr[SIZE]={}; //使用gcc -D可以宏定義這個(gè)數(shù)字

  for(num = 0;num <= SIZE - 1;num++)

  {

  arr[num]=num;

  printf("%d ",arr[num]);

  }

  printf("\n");

  return 0;

  }

  gcc -DSIZE=4 define.c

  輸出結(jié)果:

  0 1 2 3

  函數(shù)宏:

  通過(guò)使用參數(shù),可以創(chuàng)建外形和作用都與函數(shù)相似的類函數(shù)宏。宏的參數(shù)也用圓括號(hào)括起來(lái)。類函數(shù)宏的定義中,用圓括號(hào)括起來(lái)一個(gè)或多個(gè)參數(shù),隨后這些參數(shù)出現(xiàn)在替換部分。

  #include

  #define SQUARE(X) X*X

  #define PR(X) printf ("The result is %d\n", X)

  int main (void)

  {

  int x = 4;

  int z;

  printf ("x = %d\n", x);

  z = SQUARE(x);

  printf ("Evaluating SQUARE(x): ");

  PR(z);

  z = SQUARE(2);

  printf ("Evaluating SQUARE(2): ");

  PR(z);

  printf ("Evaluating 100/SQUARE(2): ");

  PR(100/SQUARE(2));

  z = SQUARE(x+2);

  printf ("Evaluating SQUARE(x+2): ");

  PR(z);

  printf ("x is %d\n", x);

  z = SQUARE(++x);

  printf ("Eavluating SQUARE(++x): ");

  PR(SQUARE (++x));

  printf ("After incrementing, x is %x\n", x);

  return 0;

  }

  輸出結(jié)果:

  x = 4

  Evaluating SQUARE(x): The result is 16

  Evaluating SQUARE(2): The result is 4

  Evaluating 100/SQUARE(2): The result is 100

  Evaluating SQUARE(x+2): The result is 14

  x is 4

  Eavluating SQUARE(++x): The result is 36

  After incrementing, x is 6

  SQUARE(x+2) 輸出結(jié)果是14,而不是想要的6*6 = 36。這是因?yàn)轭A(yù)處理器不進(jìn)行計(jì)算,而只進(jìn)行字符串替換。在出現(xiàn)x的地方,預(yù)處理都用字符串 x+2進(jìn)行替換。x*x 變?yōu)?x+2*x+2 根據(jù)運(yùn)算符優(yōu)先級(jí),則結(jié)果為 14

  100/SQUARE(2)輸出結(jié)果是 100,而不是想要的 25。因?yàn)椋鶕?jù)優(yōu)先級(jí)規(guī)則,表達(dá)式是從左到右求值的。

  100/2*2 = 100

  要處理前面兩個(gè)示例中的情況,需要如下定義:

  #define SQUARE(x) ((x) * (x))

  從中得到的經(jīng)驗(yàn)是使用必須的足夠多的圓括號(hào)來(lái)保證以正確的順序進(jìn)行運(yùn)行和結(jié)合。

  SQUARE(++x) 根據(jù)編譯器的不同會(huì)出現(xiàn)兩種不同的結(jié)果。解決這個(gè)問(wèn)題的最簡(jiǎn)單的方法是避免在宏的參數(shù)中使用++x。一般來(lái)說(shuō),在宏中不要使用增量或減量運(yùn)算符。

  參看:C 語(yǔ)言再學(xué)習(xí) -- 運(yùn)算符與表達(dá)式

  利用宏參數(shù)創(chuàng)建字符串:#運(yùn)算符

  在類函數(shù)宏的替換部分中,#符號(hào)用作一個(gè)預(yù)處理運(yùn)算符,它可以把語(yǔ)言符號(hào)轉(zhuǎn)化為字符串。

  例如:如果x是一個(gè)宏參量,那么#x可以把參數(shù)名轉(zhuǎn)化為相應(yīng)的字符串。該過(guò)程稱為字符串化。

  #include

  #define PSQR(x) printf ("The square of " #x" is %d\n", ((x)*(x)))

  int main (void)

  {

  int y = 2;

  PSQR (y);

  PSQR (2 + 4);

  return 0;

  }

  輸出結(jié)果:

  The square of y is 4

  The square of 2 + 4 is 36

  #include

  #include

  #define VEG(n) #n

  int main()

  {

  char str[20];

  strcpy(str,VEG(num));//num

  printf("%s\n",str);//拷貝

  return 0;

  }

  輸出結(jié)果:

  num

  預(yù)處理器的粘合劑:##運(yùn)算符

  和#運(yùn)算符一樣,##運(yùn)算符可以用于類函數(shù)宏的替換部分。另外,##還可用于類對(duì)象宏的替換部分。這個(gè)運(yùn)算符把兩個(gè)語(yǔ)言符號(hào)組合成單個(gè)語(yǔ)言符號(hào)。

  #include

  #define XNAME(n) x##n

  #define PRINT_XN(n) printf ("x"#n" = %d\n", x##n)

  int main (void)

  {

  int XNAME (1) = 14; //變?yōu)?int x1 = 14;

  int XNAME (2) = 20; //變?yōu)?int x2 = 20;

  PRINT_XN (1); //變?yōu)?printf ("x1 = %d\n", x1);

  PRINT_XN (2); //變?yōu)?printf ("x2 = %d\n", x2);

  return 0;

  }

  輸出結(jié)果:

  x1 = 14

  x2 = 20

  宏用于簡(jiǎn)單函數(shù):

  #include

  #define MAX(x,y) ((x)>(y) ? (x) : (y)) /*比較大小*/

  #define ABS(x) ((x) < 0 ? -(x) : (x)) /*絕對(duì)值*/

  #define ISSIGN(x) ((x) == '+' || (x) == '-' ? 1 : 0) /*正負(fù)號(hào)*/

  int main()

  {

  printf ("較大的為: %d\n", MAX(5,3));

  printf ("絕對(duì)值為: %d\n", ABS (-2));

  printf ("正負(fù)號(hào)為: %d\n", ISSIGN ('+'));

  return 0;

  }

  輸出結(jié)果:

  較大的為: 5

  絕對(duì)值為: 2

  正負(fù)號(hào)為: 1

  下面是需要注意的幾點(diǎn):

  1、宏的名字中不能有空格,但是在替代字符串中可以使用空格。ANSI C 允許在參數(shù)列表中使用空格。

  2、用圓括號(hào)括住每個(gè)參數(shù),并括住宏的整體定義。

  3、用大寫字母表示宏函數(shù)名,便于與變量區(qū)分。

  4、有些編譯器限制宏只能定義一行。即使你的編譯器沒(méi)有這個(gè)限制,也應(yīng)遵守這個(gè)限制。

  5、宏的一個(gè)優(yōu)點(diǎn)是它不檢查其中的變量類型,這是因?yàn)楹晏幚碜址妥址,而不是?shí)際值。

  面試:用預(yù)處理指令#define 聲明一個(gè)常數(shù),用以表明1年中有多少秒(忽略閏年問(wèn)題)

  #define SEC (60*60*24*365)UL

  考察內(nèi)容:

  1、懂得預(yù)處理器將為你計(jì)算常量表達(dá)式的值,因此,可直接寫出你是如何計(jì)算一年中有多少秒而不是計(jì)算出實(shí)際的值,這樣更清晰而沒(méi)有代價(jià)。

  2、意識(shí)到這個(gè)表達(dá)式將使一個(gè)16 位機(jī)的整形數(shù)溢出,因此要用到長(zhǎng)整形符號(hào) L ,告訴編譯器這個(gè)常數(shù)是長(zhǎng)整形數(shù)。

  3、如果你在你的表達(dá)式中用到UL(表示無(wú)符號(hào)長(zhǎng)整型),那么你有了一個(gè)好的起點(diǎn)。

  面試:寫一個(gè)“標(biāo)準(zhǔn)”宏MIN ,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè)

  #define MIN(A,B) ((A) <= (B) ? (A) : (B))

  考察內(nèi)容:

  1、三目表達(dá)式的使用

  2、使用必須的足夠多的圓括號(hào)來(lái)保證以正確的順序進(jìn)行運(yùn)行和結(jié)合

  3、進(jìn)一步討論,在宏中不要使用增量或減量運(yùn)算符

  參看:宏名必須用大寫字母嗎?

  研究:C語(yǔ)言中用宏定義(define)表示數(shù)據(jù)類型和用typedef定義數(shù)據(jù)類型有什么區(qū)別?

  宏定義只是簡(jiǎn)單的字符串代換,是在預(yù)處理完成的,而typedef是在編譯時(shí)處理的,它不是作簡(jiǎn)單的代換,而是對(duì)類型說(shuō)明符重新命名。被命名的標(biāo)識(shí)符具有類型定義說(shuō)明的功能。

  請(qǐng)看下面的例子:

  #define P1 int *

  typedef (int *) P2

  從形式上看這兩者相似,但在實(shí)際使用中卻不相同。

  下面用P1、P2說(shuō)明變量時(shí)就可以看出它們的區(qū)別:

  P1 a, b; 在宏代換后變成: int *a, b; 表示 a 是指向整型的指針變量,而 b 是整型變量。

  P2 a, b; 表示a,b都是指向整型的指針變量。因?yàn)镻IN2是一個(gè)類型說(shuō)明符。

  由這個(gè)例子可見(jiàn),宏定義雖然也可表示數(shù)據(jù)類型, 但畢竟是作字符代換。在使用時(shí)要分外小心,以避出錯(cuò)。

  總結(jié),typedef和#define的不同之處:

  1、與#define不同,typedef 給出的符號(hào)名稱僅限于對(duì)類型,而不是對(duì)值。

  2、typedef 的解釋由編譯器,而不是是處理器執(zhí)行。

  3、雖然它的范圍有限,但在其受限范圍內(nèi),typedef 比 #define 更靈活。

  用于定義字符串,尤其是路徑

  A),#define ENG_PATH_1 E:\English\listen_to_this\listen_to_this_3

  B),#define ENG_PATH_2 “ E:\English\listen_to_this\listen_to_this_3”

  A 為 定義路徑, B 為定義字符串

  C), #define ENG_PATH_3 E:\English\listen_to_this\listen\

  _to_this_3

  還沒(méi)發(fā)現(xiàn)問(wèn)題?這里用了 4 個(gè)反斜杠,到底哪個(gè)是接續(xù)符?回去看看接續(xù)符反斜杠。反斜杠作為接續(xù)符時(shí),

  在本行其后面不能再有任何字符,空格都不行。所以,只有最后一那給 ENG_PATH_1 加上雙引號(hào)不就成了:“ENG_PATH_1”。但是請(qǐng)注意:有的系統(tǒng)里規(guī)定路徑的要用雙反斜杠“ \\” ,比如:

  #define ENG_PATH_4 E:\\English\\listen_to_this\\listen_to_this_3

【C語(yǔ)言#define的用法】相關(guān)文章:

C語(yǔ)言for語(yǔ)句用法詳解11-19

c語(yǔ)言問(wèn)號(hào)冒號(hào)的用法01-08

c語(yǔ)言大括號(hào)的用法11-28

c語(yǔ)言中time函數(shù)的用法03-20

C語(yǔ)言預(yù)定義宏用法03-30

C語(yǔ)言中strpbr()函數(shù)的用法03-19

C語(yǔ)言assert的用法有哪些04-02

c語(yǔ)言位運(yùn)算符的用法指導(dǎo)12-04

C語(yǔ)言學(xué)習(xí)中的指針用法教程04-01