C語言中的 define預處理指令老手都是這樣用,你全都掌握了嗎?

2021-01-07 C語言知識傳播者

C語言有許多預處理命令,#define是其預處理命令之一。所有預處理命令以「#」號開頭,如包含命令#include,標準錯誤指令#error,#pragma指令等。#define指令用於宏定義,可以提高原始碼的可讀性,為編程提供方便,一般放在源文件的前面部分。

本文簡要總結#define指令的多種用法及其注意事項。

1、 無參數定義

定義形式如下:

#define 標識符 字符串

無參數宏定義不含參數,常用於常量定義或重新定義數據類型。

1) 常量定義

在編程應用中,對於頻繁使用或具有特殊意義的數字可以採用宏定義,在編譯預處理時,對程序中所有出現的宏名,都用定義的字符串代替。如:#define PI 3.1416,這樣在對源程序作編譯時,將先由預處理程序進行宏代換,即用3.1416去置換所有的宏名PI,然後再進行編譯。切記不要定義成#define PI=3.1416,這是新手常犯錯誤。

如果不再使用已定義過的宏,可以用#undef命令終止該宏定義的作用域。

2) 重新定義數據類型

可以把已有類型定義成一個你想要的新類型名,如#define FT float。編寫源程序時可用FT替代float;在編譯預處理時則將FT全都替換成float。

2、 帶參數定義

C語言允許宏帶有參數,使用帶參數的宏定義可完成函數調用的功能,又能減少系統開銷,提高運行效率。同時也不需要像函數調用那樣保留現場,以便子函數執行結束後能返回繼續執行,同樣在子函數執行完後要恢復調用函數的現場,這都帶來一定的時間開銷。與函數類似,在宏定義中的參數稱為形式參數,在宏調用中的參數稱為實際參數。對帶參數的宏,在調用中,不僅要宏展開,而且要用實參去代換形參。

帶參數宏定義的一般形式為:

#define 宏名(形參表) 字符串

如定義一個求兩個量的乘積的帶參數宏,可以按如下形式定義:

#define MULTIPLY(a,b) ((a)*(b))

假如源程序中有MULTIPLY(5,6),則在編譯預處理時,會用((5)*(6))來替代。

注意,在定義宏時一定要把字符串用括號括起來,並且每一個參數均需括起來,否則程序有可能不會按照你的意圖執行。如果你把宏簡單地定義成了如下形式:

#define MULTIPLY(a,b) a*b

此種定義下,若源程序中有MULTIPLY(2+3,3+3),編譯預處理時不會做任何計算,即絕不會先計算2+3和3+3再替換,而是直接替換。那麼結果將會是2+3*3+3=14,已經不再符合編程的預期結果30。

3、 多行定義

#define可以進行多行定義,用於替代多行語句代碼。定義形式如下:

#define MACRO(參數列表)do{ \

語句1; \

… \

語句n; \

}while(0)

切記,需要在每行的末尾一定要加上「\」,起到換行的作用。

4、 單行定義

#define Conn(x,y) x##y /* x##y表示什麼?表示x連接y */

#define ToChar(x) #@x /* #@x,其實就是給x加上單引號 */

#define ToString(x) #x /* #x是給x加雙引號 */

5、 用#define來處理頭文件嵌套包含問題

由於頭文件包含可以嵌套,那麼c文件有可能包含多次同一個頭文件,就可能出現重複定義的問題的,那麼可以就通過條件編譯開關來避免重複包含,一般頭文件可以做如下定義:

#ifndef __headerfileXXX__

#define __headerfileXXX__

文件內容

#endif

6、 #define特性及使用說明

1) 宏名一般用大寫,且宏定義末尾不加分號;

2) 宏定義通常在文件的最開頭,作用域通常從定義處到文件末尾,也可以用#undef命令提前終止宏定義的作用域;

3) 宏定義不存在類型問題,它的參數也是無類型的,編譯預處理不做語法檢查,不分配內存;

4) 字符串" "中永遠不包含宏;

5) 編程時使用宏可提高程序的通用性和易讀性,減少不一致性,減少輸入錯誤和便於修改。

相關焦點

  • C語言中typedef與define的這些區別值得關注
    因此也讓許多初學者產生迷惑,分不清楚到底有什麼區別,今天作者來總結一下供大家參考,看了本文相信大家能夠掌握。1、 從功能上來說有不同define指令用於宏定義,可以提高原始碼的可讀性,為編程提供方便,一般放在源文件的前面部分。
  • C語言的那些小秘密之預處理
    預處理是C語言的一個重要知識點,它能改善程序設計的環境,有助於編寫易移植、易調試的程序。因此,我們有必要掌握好預處理命令,在自己編程的時候靈活的使用它,使得編寫的程序結構優良,更加易於調試和閱讀。接下來我儘可能的把預處理中重要知識點向讀者講解清楚,使讀者能夠在自己以後編程的過程中熟練的使用預處理命令。
  • C語言預處理命令分類和工作原理
    本文轉載自【微信公眾號:strongerHuang,ID:strongerHuang】經微信公眾號授權轉載,如需轉載與原文作者聯繫C語言編程過程中,經常會用到如 #include、#define 等指令,這些標識開頭的指令被稱為預處理指令,預處理指令由預處理程序(預處理器)操作。
  • 《邊學邊用攻破C語言》第17集 宏定義define的用法
    《邊學邊用攻破C語言》是專門為單片機初學者準備的C語言基礎視頻教學課程,是科技老頑童
  • C語言 | #define命令
    「要成為絕世高手,並非一朝一夕,除非是天生武學奇才,但是這種人…萬中無一」這道理放在C語言學習上也一併受用
  • C中的define應用
    define是在C語言中應用很多的預處理命令。相信基礎的方法大家都已經掌握很熟了,但就像慶叔反覆強調的,基礎知識都在這裡,關鍵是如何去應用。學習晶片,掌握了寄存器的配置,也就對晶片基本掌握了,但學習晶片學習的其實不是晶片本身,而是晶片的應用,應用就千變萬化了,怎樣合理設計引腳,應用哪些寄存器,才是做好一個應用的關鍵。那麼define其實也是這樣,基礎都很了解,但怎麼去應用它才是關鍵。本文就從一個實際的應用來介紹define這個功能。
  • C語言中的變量存儲類型static老手都這樣用
    ,你還記得嗎?static老手都這樣用。1、 先來回顧C語言變量C語言中變量值的存儲位置有兩類:CPU的寄存器和內存。2、 Static關鍵字用法C語言中,無論是變量還是函數都可以用static關鍵字來修飾。具體用法我們分別來看。
  • STM32中C語言知識點:初學者必看,老鳥複習(長文總結)
    其實C語言是可以邊學單片機邊學的,學單片機的一些例程中,遇到不懂的C語言知識,再去查相關的知識點,這樣印象才會深刻些。下面就列出了一些STM32中重要的C語言知識點,初學的小夥伴可以多讀幾遍,其中大多知識點之前都有寫過,這裡重新整理一下,更詳細地分析解釋可以閱讀附帶的連結。
  • 強制了解const,C語言變量和常量!C語言系列教程!編號零零六
    字符常量字符常量是用單引號括起來的符號。字符常量的最大長度為一個字符。例 'A' ,'2' ,'+'在C程式語言中,有一些稱為轉義序列的預定義字符常量。每個轉義序列都有自己的特殊功能,每個轉義序列都以「\」符號為前綴。這些轉義序列用於名為'printf()'的輸出函數中。
  • C語言中宏定義的用法
    說到宏定義,我們應該先了解什麼是預處理指令,相信大家並不會陌生,之前我們編程時,程序的開頭#include指令,#define指令都是預處理指令,它能使我們的編譯更加的高效,便捷,因此C語言中是允許用戶自己加入一些特定的預處理指令的。
  • 長文 | 花了兩天時間整理了STM32中的一些C語言知識點,初學者福利!老鳥複習
    說在前面的話 一位初學單片機的小夥伴讓我推薦C語言書籍,因為C語言基礎比較差,想把C語言重新學一遍,再去學單片機,我以前剛學單片機的時候也有這樣子的想法。其實C語言是可以邊學單片機邊學的,學單片機的一些例程中,遇到不懂的C語言知識,再去查相關的知識點,這樣印象才會深刻些。
  • 《C語言入門指南》中篇
    GitHhub搜:ye13函數1、為完成某一功能的程序指令(語句)的集合,稱為函數。2、在C語言中,函數分為: 自定義函數、系統函數(查看C語言函數手冊) 3、函數還有其它叫法,比如方法等,在本視頻課程中,我們統一稱為 函數。
  • C/C+編程筆記:C語言預處理命令是什麼?不要以為你直接寫#就行!
    這些在編譯之前對源文件進行簡單加工的過程,就稱為預處理(即預先處理、提前處理)。 預處理主要是處理以#開頭的命令,例如#include 等。預處理命令要放在所有函數之外,而且一般都放在源文件的前面。 預處理是C語言的一個重要功能,由預處理程序完成。
  • C語言#define和typedef的用法區別,以及陷阱
    ,typedef 和 #define是最常用語句,可能很多工作過幾年的工程師都沒有去深究過它們的一些用法和區別。#define為一宏定義語句,通常用它來定義常量(包括無參量與帶參量),以及用來實現那些「表面似和善、背後一長串」的宏,它本身並不在編譯過程中進行,而是在這之前(預處理過程)就已經完成了,但也因此難以發現潛在的錯誤及其它代碼維護問題,比如:#define INT int#define TRUE 1#define Add
  • C語言基礎知識
    pow(x, y)函數C 和 Python 語言的 pow(x, y) 方法都是用於返回 (x 的 y 次方) 的值,C 語言中其原型為:double pow(double x, double y)。下表列出了關於標準浮點類型的存儲大小、值範圍和精度的細節:IO 函數sprintf()函數fopen()函數fwrite()函數預編譯指令
  • C語言編程核心要點
    數組是靜態的,在定義的時候,數組的長度就已經確認,運行中無法伸縮,所以有時候我們不得不為應付擴充多分配一些空間。數組元素不管用多用少,它都在哪裡,有時候,我們會用一個int n去界定數組實際被使用的元素個數。函數函數封裝行為,是模塊化的最小單元,函數使得邏輯復用變得可能。
  • 【編程經驗】C語言中的宏陷阱 #define SQU(x) x*x
    點擊藍字關注我們咳咳咳,今天講講C中宏定義(片面),希望對小夥伴們有幫助,開始了:有同學寫過或者想寫這樣的宏定義嗎?求兩個或幾個數的乘積: #define SQU(x) x*x我們正常使用沒有問題:但如果這樣寫呢?哎呀,竟然不是100了,難道SQU(10)和SQU(5+5)不等價嗎?5+5不是10嗎?的確,這裡SQU(10)和SQU(5+5)的確不等價!原因在於,宏定義的本質是文本替換!
  • C語言陷阱與技巧第2節,使用inline函數可以提升程序效率,但是讓...
    Linux 內核中經常像下面這樣,將內聯函數放在調用它的函數前面,請看C語言代碼:staticinlinevoid set_value(unsignedint val){ ...}int test_inline(){ set_value(3); ...}
  • c語言程序設計自學教程
    詩人魯米說:「你生而有翼,為何竟願一生匍匐前進,形如蟲蟻?」這是一聲直擊靈魂的質問.是啊,人人生而有翼,只要肯努力地展開雙翅,朝天空飛去,誰都能擁有一片廣闊的天地.可為什麼,你只是一動不動地匍匐在地,形同蟲蟻?
  • 編程基礎-C程序的組成
    1、C工程的組成c程序是由一個或者多個.c文件和.h文件組成的。其中 .c文件是c原始碼文件,是程序具體實現的部分。.h文件時C的頭文件,用來聲明.c文件中函數的。也可以申明自定義的數據。如下圖,我定義了一個宏:#define kAD_MAX_DIM 5。