激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - 詳解C語言#define預處理宏定義

詳解C語言#define預處理宏定義

2021-12-27 15:17vbnetcx C/C++

本文主要介紹了C語言#define預處理宏定義,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

#define介紹:

C語言里可以用#define定義一個標識符來表示一個常量。特點是:定義的標識符不占內存,只是一個臨時的符號,預編譯后這個符號就不存在了,也不做類型定義。預編譯又叫預處理。預編譯就是編譯前的處理。這個操作是在正式編譯之前由系統自動完成的。

#define又稱宏定義,標識符為所定義的宏名,簡稱宏。標識符的命名規則和變量的命名規則是一樣的。#define的功能是將標識符定義為其后的常量,一經定義,程序中就可以直接用標識符來表示這個常量,也就是文本替換。變量名表示的是一個變量,但宏名表示的是一個常量,可以給變量賦值,但絕不能給常量賦值。

宏定義最大的好處是方便程序的修改。使用宏定義可以用宏代替一個在程序中經常使用的常量。這樣,當需要改變這個常量的值時,就不需要對整個程序一個一個進行修改,只需修改宏定義中的常量就行了。且當常量比較長時,使用宏就可以用較短的有意義的標識符來代替它,這樣編程的時候就會更方便,不容易出錯。因此,宏定義的優點就是方便和易于維護。

#define宏定義無參的一般形式為:#define  標識符 常量

注意最后沒有分號,因為宏不是語句,結尾不用加分號,否則會被替換進進程中。還有一點就是宏名最好用大寫字母加下劃線組成,以此來區分變量名。

來看一個#define宏定義無參的例子:

?
1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
#define PI 3.1415926//標識符或宏名叫PI 常量是個浮點型 作用是圓周率
#define R 2//標識符或宏名叫R 常量是個整型 作用是圓的半徑
#define PRINT "半經為2的圓 面積=%lf\n"//標識符或宏名叫PRINT 常量是個字符串 作用是代替了printf()函數的第一個參數
int main()
{
    printf(PRINT,PI*R*R);//在這里PRINT被替換成"半經為2的圓 面積=%lf" PI被替換成3.1415926 R被替換成2
    printf("半經為2的圓 面積=%lf\n",3.1415926*2*2);//這句是上面一句代碼替換后的代碼
    return 0;
}

#define宏定義有參的一般形式為:#define  標識符(參數表) 表達式

帶參數的宏定義,宏名中不能有空格,宏名與形參表之間也不能有空格,而形參表中形參之間可以有空格。

來看一個#define宏定義有參的例子:

?
1
2
3
4
5
6
7
8
#include<stdio.h>
#define SQUARE(x) x*x//標識符或宏名叫SQUARE 表達式是x*x 作用是算x的平方
int main()
{
 printf("%d %d\n",SQUARE(3),SQUARE(4));//SQUARE(3)被替換成3*3 SQUARE(4)被替換成4*4
 printf("%d %d\n",3*3,4*4);//這句是上面一句代碼替換后的代碼
 return 0;
}

我門來稍微改動下代碼:

?
1
2
3
4
5
6
7
#include<stdio.h>
#define SQUARE(x) x*x//標識符或宏名叫SQUARE 表達式是x*x 作用是算x的平方
int main()
{
 printf("%d %d\n",SQUARE(2+1),SQUARE(3+1));
 return 0;
}

 這里只是把傳的參數3被改成了2+1,4被改成了3+1,可能有些朋友會說2+1=3,3+1=4,答案不就和剛才一樣嘛。其實不是,因為#define宏定義只是簡單的文本替換,那應該被替換成什么呢。SQUARE(2+1)和SQUARE(3+1)分別替換成2+1*2+1和3+1*3+1, 那么最終答案自然是5和7了。那么如何杜絕這個問題呢?

很簡單,只要在傳參時多加一層小括號:

?
1
2
3
4
5
6
7
8
#include<stdio.h>
#define SQUARE(x) x*x//標識符或宏名叫SQUARE 表達式是x*x 作用是算x的平方
int main()
{
 printf("%d %d\n",SQUARE((2+1)),SQUARE((3+1)));//SQUARE((2+1))被替換成(2+1)*(2+1) SQUARE((3+1))被替換成(3+1)*(3+1)
 printf("%d %d\n",(2+1)*(2+1),(3+1)*(3+1));//這句是上面一句代碼替換后的代碼
 return 0;
}

 如果覺得這樣太繁雜,麻煩了,那么直接在宏定義的表達式那里的每個參數都加上小括號:

?
1
2
3
4
5
6
7
8
#include<stdio.h>
#define SQUARE(x) (x)*(x)//標識符或宏名叫SQUARE 表達式是x*x 作用是算x的平方
int main()
{
 printf("%d %d\n",SQUARE(2+1),SQUARE(3+1));//SQUARE((2+1))被替換成(2+1)*(2+1) SQUARE((3+1))被替換成(3+1)*(3+1)
 printf("%d %d\n",(2+1)*(2+1),(3+1)*(3+1));//這句是上面一句代碼替換后的代碼
 return 0;
}

我們又來稍微改動下代碼:

?
1
2
3
4
5
6
7
#include<stdio.h>
#define SQUARE(x) (x)*(x)//標識符或宏名叫SQUARE 表達式是x*x 作用是算x的平方
int main()
{
 printf("%d %d\n",9/SQUARE(3),16/SQUARE(4));
 return 0;
}

這里在傳參數之前加了個除法,那么3*3后是9,再被9除,等于1,4*4后是16,再被16除,等于1,那么預想的最終答案就是1和1了,其實也不是。再來一次文本替換,9/SQUARE(3)和16/SQUARE(4)分別替換成9/(3)*(3)和16/(4)*(4), 那么最終答案自然是9和16了。那么又如何杜絕這個問題呢?

也很簡單,只要在傳參時多加一層小括號:

?
1
2
3
4
5
6
7
8
#include<stdio.h>
#define SQUARE(x) (x)*(x)//標識符或宏名叫SQUARE 表達式是x*x 作用是算x的平方
int main()
{
 printf("%d %d\n",9/(SQUARE(3)),16/(SQUARE(4)));//9/(SQUARE(3))和16/(SQUARE(4))分別替換成9/((3)*(3))和16/((4)*(4))
 printf("%d %d\n",9/((3)*(3)),16/((4)*(4)));//這句是上面一句代碼替換后的代碼
 return 0;
}

如果依然覺得這樣太繁雜,麻煩了,那么直接在宏定義的表達式那里的整個表達式都加上小括號:

?
1
2
3
4
5
6
7
8
#include<stdio.h>
#define SQUARE(x) ((x)*(x))//標識符或宏名叫SQUARE 表達式是x*x 作用是算x的平方
int main()
{
 printf("%d %d\n",9/SQUARE(3),16/SQUARE(4));//9/(SQUARE(3))和16/(SQUARE(4))分別替換成9/((3)*(3))和16/((4)*(4))
 printf("%d %d\n",9/((3)*(3)),16/((4)*(4)));//這句是上面一句代碼替換后的代碼
 return 0;
}

表達式也可以寫多個語句:

?
1
2
3
4
5
6
7
8
9
#include<stdio.h>
#define AB(a,b) a=i+5,b=j+3
int main()
{
    int i=3,j=5,m=0,n=0;
    AB(m,n);//AB(m,n)被替換成m=i+5,n=j+3
    printf("%d %d\n",m,n);
    return 0;
}

#運算符:

#運算符的作用就是將#后邊的宏參數進行字符串的操作,也就是將#后邊的參數兩邊加上一對雙引號使其成為字符串。例如param是一個宏的形參,則替換文本中的#param被系統轉化為"param",這個轉換過程即為字符串化。如下代碼:

?
1
2
3
4
5
6
7
8
#include<stdio.h>
#define TEST(param) #param//標識符或宏名叫TEST 表達式是#param 作用是把param參數轉換為字符串
int main()
{
    printf("%s\n",TEST(換行前\n第一次換行\n第二次換行));//TEST(換行前\n第一次換行\n第二次換行)被替換成"換行前\n第一次換行\n第二次換行"
    printf("換行前\n第一次換行\n第二次換行\n");//這句是上面一句代碼替換后的代碼
 return 0;
}

##運算符:

##運算符也可以用在替換文本中,它的作用起到粘合的作用,即將兩個宏參數連接為一個數。如下代碼:

?
1
2
3
4
5
6
7
8
#include<stdio.h>
#define TEST(param1,param2) (param1##param2)//標識符或宏名叫TEST 表達式是(param1##param2) 作用是把param1參數和param2參數和連接為一個數
int main()
{
    printf("%d\n",TEST(12,34));//TEST(12,34)被替換成(1234)
    printf("%d\n",(1234));//這句是上面一句代碼替換后的代碼
    return 0;
}

可變宏...和__VA_ARGS__:

可變宏...和__VA_ARGS__的作用主要是為了方便管理軟件中的打印信息。在寫代碼或DEBUG時通常需要將一些重要參數打印出來,但在軟件發行的時候不希望有這些打印,這時就用到可變參數宏了。如下代碼:

?
1
2
3
4
5
6
7
8
#include<stdio.h>
#define PRINT(...) printf(__VA_ARGS__)//標識符或宏名叫PRINT 表達式是printf(__VA_ARGS__) __VA_ARGS__被用在替換文本中,來表示省略號...代表了什么
int main()
{
    PRINT("hello\n");//PRINT("hello\n")被替換成printf("hello\n")
    printf("hello\n");//這句是上面一句代碼替換后的代碼
    return 0;
}

在宏定義中,形參列表的最后一個參數為省略號...,而__VA_ARGS__被用在替換文本中,來表示省略號...代表了什么。

開發項目中常用的宏定義:

防止頭文件被重復包含:

?
1
2
3
4
#ifndef COMDEF_H
#define COMDEF_H
//頭文件的內容
#endif

得到一個制定地址上的一個字節或字:

?
1
2
#define MEM_B(X) (*((byte*)(x)))
#define MEM_W(X) (*((word*)(x)))

求最大值與最小值:

?
1
2
#define MAX(x,y)  ((x)>(y)?(x):(y))
#define MIN(x,y)  ((x)<(y)?(x):(y))

得到一個結構體中field所占用的字節數:

?
1
#define FSIZ(type,field)  sizeof(((type*)0)->field)

得到一個field在結構體中的偏移量:

?
1
#define FPOS(type,field)\((dword)&(((type*)0)->field)

按照LSB格式把兩個字節轉化為一個word:

?
1
#define FLIPW(ray) (((word)(ray)[0]*256)+(ray)[1])

按照LSB格式將一個WORD轉化為兩個字節:

?
1
#define FLOPW(ray,val)  (ray)[0]=((val)/256);(ray)[1]=((val)&0xFF)

得到一個變量的地址:

?
1
2
#define B_PTR(var) ((byte*)(void*)&(var))
#define W_PTR(var) ((word*)(void*)&(var))

得到一個字的高位與低位字節:

?
1
2
#define WORD_LO(xxx) ((byte)((word)(xxx)&255))
#define WORD_HI(xxx) ((byte)((word)(xxx)>>8))

用宏得到一個數組所含的元素個數:

?
1
#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))

 到此這篇關于詳解C語言#define預處理宏定義 的文章就介紹到這了,更多相關C語言#define預處理宏定義 內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/vbnetcx/article/details/120042916

延伸 · 閱讀

精彩推薦
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
主站蜘蛛池模板: 久久精品免费国产 | 中文字幕综合在线观看 | 久久精品中文字幕一区二区三区 | 亚洲第一男人天堂 | 国产精品视频一区二区三区综合 | 国产精品一区视频 | 国产91在线亚洲 | 一级电影免费看 | 羞羞电影在线观看www | 免费看综艺策驰影院 | 亚洲电影在线观看高清免费 | 成熟女人特级毛片www免费 | 国产69精品久久久久99尤 | 亚州精品在线视频 | av在线免费观看不卡 | 羞羞网站在线看 | 色淫视频| 亚洲国产视频在线 | 免费国产人成网站 | 亚洲精品一区二区三区在线看 | a黄网站| 大号bbwassbigav头交 | 免费毛片在线视频 | 成年人黄色免费网站 | v11av在线视频成人 | 久久久国产精品视频 | 意大利av在线 | 国产精品91在线 | av资源在线 | 一级观看免费完整版视频 | 欧洲精品色 | 欧美日韩一 | 噜噜噜躁狠狠躁狠狠精品视频 | 激情综合婷婷久久 | 黄色1级视频 | 久久国产精品小视频 | 精品一区二区免费 | 电影一级毛片 | 国产精品v片在线观看不卡 成人一区二区三区在线 | hdbbwsexvideo| 天天透天天狠天天爱综合97 |