C語言宏相關操作

  • 宏名稱通常都是由大寫英文字母構成的
  • 宏名稱里不可以包含空格
  • 用宏給數字起名字的時候不可以使用賦值運算符,不要自增自減
  • 可以在編寫程序的時候直接使用宏名稱替代數字,編譯器在編譯的時候會把程序里的宏替換成它所代表的數字

1. 為什么要使用宏?

1.1 名稱直觀:

宏可以用有意義的名稱,比如使用PI去替代抽象的數值3.14,讓代碼更易懂。開發者看到PI時能直接聯想到“圓周率”,而無需記憶數字的含義,尤其是在復雜程序中,這種直觀性能顯著提高代碼的可理解性。

1.2 便于更新:

當需要修改宏代表的值時,如PI的精度從3.14調整為3.14159,只需在宏定義處修改一次,編譯器會在預處理階段自動替換所有引用該宏的地方。如果不使用宏,直接在代碼中多出寫死數值,修改時需要逐個查找并替換,不僅繁瑣,還容易遺漏,增加出錯風險。

2. 無參宏(基本宏)

#include<stdio.h>// 定義無參宏PI,代表圓周率3.14159
// 宏的作用:用有意義的名稱替代常量,提高代碼可讀性
// 后續若需調整精度(如改為3.1415926),只需修改此處即可,所有引用處會自動替換
#define PI (3.14159)int main(void){float r = 0;printf("請輸入一個半徑值:");scanf("%f",&r);// 計算圓的面積:使用宏PI替代3.14159,代碼更直觀printf("圓的面積是:%g\n", PI * r * r);// 計算圓的周長:同樣使用宏PI,確保所有圓周率值一致printf("圓的周長是:%g\n", 2 * PI * r);return 0;
}

3. 帶參宏(類似函數的宏)

帶參宏的特性:僅在預處理階段做文本替換,不進行參數類型檢查,適用于多種數據類型

#include<stdio.h>// 定義帶參宏SQUARE,用于計算參數的平方
// 宏參數x:表示要計算平方的數值或表達式
// 替換文本((x)*(x)):外層和內層都加括號是為了避免因運算符優先級導致的計算錯誤
#define SQUARE(x) ((x)*(x)) int main(void){// 調用帶參宏SQUARE,參數為整數5// 預處理階段會替換為:((5)*(5)),結果為25printf("%d\n", SQUARE(5));// 調用帶參宏SQUARE,參數為浮點數5.5// 預處理階段會替換為:((5.5)*(5.5)),結果為30.25// 體現宏不檢查類型的特性,可同時處理整數和浮點數printf("%lg\n", SQUARE(5.5));// 調用帶參宏SQUARE,參數為表達式2+3// 預處理階段會替換為:((2+3)*(2+3)),結果為25// 因宏定義中參數x被括號包裹,避免了"2+3*2+3"的錯誤計算printf("%d\n", SQUARE(2+3));return 0;
}

4. 編譯時定義宏(通過編譯選項)

無需在代碼中用#define定義,可通過編譯器選項-D在編譯時指定宏的值

適用于需要根據不同場景(如調試/發布版本、不同硬件配置)動態修改宏值的場景

語法:gcc -D 宏名=值 源文件 -0 輸出文件

例如:gcc -DSIZE=10 test.c -o test(定義SIZE為10)

也可以gcc -D SIZE=10 test.c -o test(定義SIZE為10)

// 代碼中無需定義SIZE,編譯時通過-D指定
#include<stdio.h>
int main(void){int arr[SIZE] = {}; // SIZE由編譯選項指定for(int i=0; i<SIZE; i++){arr[i] = i + 100;}for(int i=0; i<SIZE; i++){printf("%d ", arr[i]);}return 0;
}

5. 宏運算符

  • #:將宏的參數轉換為字符串(字符串化)。
    例:#define STR(x) #x,則STR(123)會替換為"123"
  • ##:將兩個標識符連接為一個新的標識符(連接符)。
    例:#define JOIN(a,b) a##b,則JOIN(num,1)會替換為num1
#include <stdio.h>// 1. #運算符:將宏參數轉換為字符串(字符串化)
#define STR(x) #x  // 定義宏STR,使用#將參數x轉換為字符串// 2. ##運算符:將兩個參數連接為一個新的標識符(連接符)
#define JOIN(a, b) a##b  // 定義宏JOIN,使用##連接a和b為新標識符int main(void) {// 測試#運算符printf("使用#運算符的結果:\n");printf("STR(123) = %s\n", STR(123));       // 替換為"123",輸出字符串"123"printf("STR(abc) = %s\n", STR(abc));       // 替換為"abc",輸出字符串"abc"printf("STR(3.14) = %s\n", STR(3.14));     // 替換為"3.14",輸出字符串"3.14"// 測試##運算符printf("\n使用##運算符的結果:\n");int num1 = 100;        // 定義變量num1int num2 = 200;        // 定義變量num2printf("JOIN(num, 1) = %d\n", JOIN(num, 1));  // 連接為num1,輸出100printf("JOIN(num, 2) = %d\n", JOIN(num, 2));  // 連接為num2,輸出200// ##運算符也可用于函數名或其他標識符int student10 = 95;    // 定義變量student10printf("JOIN(student, 10) = %d\n", JOIN(student, 10));  // 連接為student10,輸出95return 0;
}

6. 預定義宏(編譯器自帶)

預定義宏占位符含義
__FILE__%s所在文件名
__func__%s所在函數名
__LINE__%d所在行號
__DATE__%s編譯該文件日期
__TIME__%s編譯該文件時間

注意:前后都是兩個下劃線

#include<stdio.h>
int main(void){int* p = NULL;int a = 10;//p = &a;if(p == NULL){printf("指針為NULL\n");// 把一個大串拆成多個小串(編譯器會自動拼接相鄰字符串)// 以下使用C語言預定義宏輸出調試信息:printf("文件:%s\n"  // __FILE__:預定義宏,所在文件名"函數:%s\n"  // __func__:預定義宏,所在函數名"行號:%d\n"  // __LINE__:預定義宏,所在行號"日期:%s\n"  // __DATE__:預定義宏,編譯該文件日期"時間:%s\n", // __TIME__:預定義宏,編譯該文件時間__FILE__, __func__, __LINE__, __DATE__, __TIME__);return -1; // 默認意外退出返回-1}return 0;      // 正常退出返回0
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/918136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/918136.shtml
英文地址,請注明出處:http://en.pswp.cn/news/918136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32內部讀寫FLASH

很多情況下&#xff0c;在STM32中寫入一些數據&#xff0c;在某些不可控因素下其數據無法保存。因此,解決此問題就要用到FLASH.什么是內部 Flash&#xff1f; Flash 是一種非易失性存儲器&#xff0c;STM32 的程序和常量數據就存在 Flash 中。它的關鍵特點是&#xff1a;特性說…

Oracle 12c + Pl/Sql windows系統下表空間創建、遷移,dmp備份導入,數據庫字符集更改

一、開發環境 操作系統&#xff1a;win11 Oracle版本&#xff1a;12c Oracle 數據庫字符集&#xff1a;AL32UTF8 Pl/Sql版本&#xff1a;14 二、表空間創建 表空間是 Oracle 數據庫中一種重要的邏輯結構&#xff0c;它是數據庫中數據文件的邏輯集合&#xff0c;用于存儲數據庫對…

GUI:QT簡介

一、什么是QT&#xff1f;Qt是一套跨平臺的 C 圖形用戶界面&#xff08;GUI&#xff09;應用程序開發框架&#xff0c;由挪威 Trolltech&#xff08;奇趣科技&#xff09;于 1991 年創建&#xff0c;2008 年被諾基亞收購&#xff0c;2012 年后由 Qt Company 負責維護。它廣泛應…

oceanbase執行execute immediate create table提示無權限

問題&#xff1a;OB庫4.2.5.4版本&#xff0c;執行到這一句的時候&#xff0c;報沒有權限&#xff1a;[rootlnob ~]# obclient -h192.168.207.28 -P2881 -ugistarlnzyob -pxxxxxx -A Welcome to the OceanBase. Commands end with ; or \g. Your OceanBase connection id is 3…

滴滴招java開發

滴滴集團 北京&#xff08;崗位信息已經過jobleap.cn授權&#xff0c;可在csdn發布&#xff09;收錄時間&#xff1a; 2025年08月01日職位描述 負責滴滴海外業務準入審核及反作弊相關系統的后端開發及系統維護&#xff1b; 職位要求 1、統招本科及以上學歷&#xff0c;計算機科…

深入解析基于Zookeeper分布式鎖在高并發場景下的性能優化實踐指南

深入解析基于Zookeeper分布式鎖在高并發場景下的性能優化實踐指南 在大規模分布式系統中&#xff0c;如何保證多個節點對同一資源的有序訪問&#xff0c;是提高系統穩定性與一致性的核心需求之一。Zookeeper 提供的分布式鎖機制&#xff0c;以其簡潔的原理和高可靠性&#xff0…

騰訊云CodeBuddy AI IDE+CloudBase AI ToolKit打造理財小助手網頁

CodeBuddy 騰訊云CodeBuddy AI IDECloudBase AI ToolKit打造理財小助手網頁 在線體驗地址&#xff1a;理財小助手 在線倉庫&#xff1a;https://cnb.cool/pickstars-2025/ai-financial-assistant &#x1f31f; Hello&#xff0c;我是摘星&#xff01; &#x1f308; 在彩虹般…

2025-08-08 李沐深度學習11——深度學習計算

文章目錄1 模型構造1.1 自定義 MLP&#xff08;多層感知機&#xff09;1.1.1 __init__ (構造函數)1.1.2 forward (前向傳播)1.2 使用自定義 MLP1.3 自定義 Sequential 類1.4 前向傳播1.5 模塊的嵌套使用2 參數管理2.1 參數訪問2.2 嵌套模型2.3 參數初始化2.4 參數共享3 自定義層…

匯編語言和高級語言的差異

匯編語言與高級語言在以下幾個方面存在重要的區別&#xff1a;缺少結構化流程控制。匯編語言不提供if/else、switch/case、for、while等高級控制結構&#xff0c;依賴于底層的無條件跳轉和條件跳轉指令來實現流程控制。這種基于標簽和跳轉的方式雖然極其靈活&#xff0c;但缺乏…

文件管理從基礎到高級:文件描述符、超大文件切片重組與快速刪除實戰

文件管理從基礎到高級&#xff1a;文件描述符、超大文件切片重組與快速刪除實戰目標讀者&#xff1a;Linux/macOS 用戶、后端/運維/數據工程師 環境默認&#xff1a;Linux&#xff08;GNU 工具鏈&#xff09;&#xff0c;macOS 類似&#xff1b;Windows 可使用 WSL1&#xff09…

RPC 解析

RPC&#xff08;Remote Procedure Call&#xff0c;遠程過程調用&#xff09;是一種讓分布式系統中的服務能夠像調用本地函數一樣調用遠程服務的通信機制。以下是其核心原理、技術實現及組件的詳細解析&#xff1a;&#x1f527; 一、RPC 核心工作原理&#xff08;10 步全流程&…

wstool的一個完整的工作流解析

moveit的倉庫源碼編譯的時候使用的是wstool來拉取倉庫的所有內容文件&#xff0c;其命令流程如下: wstool init src wstool merge -t src https://raw.githubusercontent.com/moveit/moveit/master/moveit.rosinstall wstool update -t src rosdep install -y --from-paths src…

對數函數分段定點實現

目錄 一、原理介紹 二、代碼實現 三、結果顯示 四、移植到C語言中的應用 4.1. 定義定點數配置和參數 4.2. 實現分段查找函數 4.3. 實現 log10 近似計算函數 4.4. &#xff08;可選&#xff09;定點數轉浮點數 一、原理介紹 之前的博文對數函數分段線性實…

qt系統--事件

文章目錄qt系統事件處理鼠標事件鼠標移動事件處理鍵盤事件定時器事件窗口移動和大小改變事件結語很高興和大家見面&#xff0c;給生活加點impetus&#xff01;&#xff01;開啟今天的編程之路&#xff01;&#xff01; 作者&#xff1a;?( ‘ω’ )?260 我的專欄&#xff1a…

Linux機器可直接使用的自動化編譯文件

還在為了Linux機器上一遍遍輸入編譯指令苦惱嗎&#xff1f;你需要make指令以及自己的makefile文件&#xff01;在makefile中寫入自己的個性化指令&#xff0c;讓編譯速度飛起&#xff0c;支持多文件編譯一下文件為個人應用&#xff0c;可以直接cp到相應項目的目錄&#xff0c;每…

Linux學習-數據結構(哈希表)

1.哈希表1.哈希算法將數據通過哈希算法映射成一個關鍵值&#xff0c;存放都在同一位置實現數據的高效存儲和查找&#xff0c;將時間復雜度盡可能降低至O&#xff08;1&#xff09;2.哈希碰撞多個數據通過哈希算法得到的鍵值相同&#xff0c;稱為產生哈希碰撞3.哈希表構建哈希表…

Google Chrome <139.0.7236.0 UAF漏洞

【高危】Google Chrome <139.0.7236.0 UAF漏洞 漏洞描述 Google Chrome 是美國谷歌&#xff08;Google&#xff09;公司的一款Web瀏覽器。 受影響版本中&#xff0c;OpenscreenSessionHost::ReportAndLogError 方法的參數使用了 std::string_view 類型來接收錯誤消息。當一…

CentOS8 Stream 網卡配置及重啟

在 CentOS 8 Stream 中&#xff0c;網卡配置已由 NetworkManager 管理&#xff0c;傳統的 ifcfg-eth0 文件仍然支持&#xff0c;但推薦使用 nmcli 或 nmtui 工具進行網絡配置和管理。以下是網卡配置及重啟的詳細步驟&#xff1a;1. 查看當前網卡狀態列出所有網卡bash復制nmcli …

SpringMvc的原理深度剖析及源碼解讀

一、springmvc啟動加載流程1、引入spring-web.jar包時&#xff0c;在這個包的META-INF/services/javax.servlet.ServletContainerInitializer文件中定義的加載類SpringServletContainerInitializer,提供給springmvc實現初始化的操作。2、在SpringServletContainerInitializer類…

【ESP32-menuconfig(1) -- Build Type及Bootloader config】

Build Type Bootloader configmenuconfig介紹Build typeCONFIG_APP_BUILD_TYPECONFIG_APP_BUILD_TYPE_PURE_RAM_APPCONFIG_APP_REPRODUCIBLE_BUILDCONFIG_APP_NO_BLOBSCONFIG_APP_COMPATIBLE_PRE_V2_1_BOOTLOADERSCONFIG_APP_COMPATIBLE_PRE_V3_1_BOOTLOADERSBootloader config…