欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言中帶返回值的宏定義方式

 更新時(shí)間:2023年02月24日 17:06:15   作者:架構(gòu)師李肯  
這篇文章主要介紹了C語(yǔ)言中帶返回值的宏定義方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

C語(yǔ)言中帶返回值的宏定義

相信大家在實(shí)際工作中,一定有遇到需要編寫(xiě)一個(gè)宏定義,且希望它能帶返回值的場(chǎng)景吧?

比如我之前就遇到一個(gè)場(chǎng)景,早期的代碼是使用函數(shù)實(shí)現(xiàn)的功能,現(xiàn)在想換成宏定義,但是又要保留之前調(diào)用函數(shù)的代碼不動(dòng),這樣我就只能想辦法寫(xiě)一個(gè)帶返回值的宏了。

宏定義編寫(xiě)

直接上demo:

#include <stdio.h>

/* always return 1 */
#define RETURN_MACRO()?? ??? ??? ?({do {} while(0);1;})
#define RETURN_MACRO2()?? ??? ??? ?1

/* return a+b */
#define A_PLUS_B_MACRO(a, b)?? ?({int ret; ret = (a) + (b); ret;})
#define A_PLUS_B_MACRO2(a, b)?? ?({int ret; ret = add((a), (b)); ret;})

int add(int a, int b)
{
?? ?return (a + b);
}

int main(int argc, const char *argv[])
{
?? ?int a = 6;
?? ?int b = 7;

?? ?printf("Hello world !\n");
?? ?printf("RETURN_MACRO: %d\n", RETURN_MACRO());
?? ?printf("RETURN_MACRO2: %d\n", RETURN_MACRO2());
?? ?printf("a + b = %d\n", A_PLUS_B_MACRO(a, b));
?? ?printf("a + b = %d\n", A_PLUS_B_MACRO2(a, b));

?? ?return 0;
}

宏定義分析

為了分析宏定義的寫(xiě)法,我們得知道宏定義最終被展開(kāi)是什么樣的。

我在之前的博文中有提到,使用gcc編譯器的話,可以在CFLAGS上加上-save-temps=obj這個(gè)編譯選項(xiàng),這樣就可以得到預(yù)編譯處理之后的文件,后綴名是.i。

我們使用編譯腳本編譯之后,得到.i文件如下:

//前面的內(nèi)容忽略

# 3 "main.c" 2
# 12 "main.c"

# 12 "main.c"
int add(int a, int b)
{
?return (a + b);
}

int main(int argc, const char *argv[])
{
?int a = 6;
?int b = 7;

?printf("Hello world !\n");
?printf("RETURN_MACRO: %d\n", ({do {} while(0);1;}));
?printf("RETURN_MACRO2: %d\n", 1);
?printf("a + b = %d\n", ({int ret; ret = (a) + (b); ret;}));
?printf("a + b = %d\n", ({int ret; ret = add((a), (b)); ret;}));

?return 0;
}

從.i文件我們可以看到,宏定義被正常展開(kāi),下面確認(rèn)下功能是否正常。

宏定義驗(yàn)證

我們執(zhí)行編譯出來(lái)的可執(zhí)行文件:

return_macro$ ./test?
Hello world !
RETURN_MACRO: 1
RETURN_MACRO2: 1
a + b = 13
a + b = 13

驗(yàn)證成功。

經(jīng)驗(yàn)總結(jié)

  • 在C語(yǔ)言里面,可以使用({aaa; bbb; ccc;})來(lái)實(shí)現(xiàn)宏定義帶返回值;這里的返回值是最后一個(gè);的值。
  • 注意里面的()和{}都不能少,否則可能會(huì)破壞代碼的語(yǔ)法結(jié)構(gòu),導(dǎo)致得不到正確的答案。

C語(yǔ)言中一些宏定義和常用的函數(shù)

typeof 關(guān)鍵字

如果你是 C++ 程序員,應(yīng)該接觸過(guò) C++11 里的 decltype 操作符,它的作用是自動(dòng)推導(dǎo)表達(dá)式的數(shù)據(jù)類型,以解決泛型編程中有些類型由模板參數(shù)決定而難以(甚至不可能)表示的問(wèn)題。

其實(shí)這個(gè)特性在 C 語(yǔ)言中也早有類似的實(shí)現(xiàn),GNU C 標(biāo)準(zhǔn)中的一個(gè)擴(kuò)展特性 typeof 作用與 decltype 類似。

__typeof__ (ret) errnum = (ret);?

snprintf()函數(shù)的作用

#include<stdio.h>
int snprintf(char* dest_str,size_t size,const char* format,...);

【函數(shù)功能】:

先將可變參數(shù) “…” 按照f(shuō)ormat的格式格式化為字符串,然后再將其拷貝至dest_str中。

如果格式化后的字符串長(zhǎng)度小于size,則將字符串全部拷貝至dest_str中,并在字符串結(jié)尾處加上‘\0’; 如果格式化后的字符串長(zhǎng)度大于或等于size,則將字符串的(size-1)拷貝至dest_str中,然后在字符串結(jié)尾處加上’\0’. 函數(shù)返回值是 格式化字符串的長(zhǎng)度。

__builtin_expect的作用

__builtin_expect(errnum != 0, 0)

這個(gè)指令是gcc引入的,作用是"允許程序員將最有可能執(zhí)行的分支告訴編譯器"。

這個(gè)指令的寫(xiě)法為:__builtin_expect(EXP, N)。意思是:EXP==N的概率很大。

一般的使用方法是將__builtin_expect指令封裝為L(zhǎng)IKELY和UNLIKELY宏。

C語(yǔ)言中常用的預(yù)定義

  • __LINE__:當(dāng)前程序行的行號(hào),表示為十進(jìn)制整型常量
  • __FILE__:當(dāng)前源文件名,表示字符串型常量
  • __DATE__:轉(zhuǎn)換的日歷日期,表示為Mmm dd yyyy 形式的字符串常量,Mmm是由asctime產(chǎn)生的。
  • __TIME__:轉(zhuǎn)換的時(shí)間,表示"hh:mm:ss"形式的字符串型常量,是有asctime產(chǎn)生的。(asctime貌似是指的一個(gè)函數(shù))
  • __STDC__:編輯器為ISO兼容實(shí)現(xiàn)時(shí)位十進(jìn)制整型常量
  • __func__:它指示所在的函數(shù)
  • __assert_perror_fail:打印一條包含錯(cuò)誤碼ERRNUM的錯(cuò)誤消息,并終止程序

反斜杠的作用

反斜杠起到換行作用,用于宏定義和字符串換行。其中宏定義中使用居多。

如果一行代碼有很多元素,導(dǎo)致太長(zhǎng)影響閱讀,可以通過(guò)在結(jié)尾加\的方式,實(shí)現(xiàn)換行,編譯時(shí)會(huì)忽略\及其后的換行符,當(dāng)做一行處理。

#define CHECK_ACTION_RETURN(expr) \
? ? if (!expr) { \
? ? ? ? printf(":failed(%d)\n", ret); \
? ? ? ? return ret; \
? ? ? ? ? ? ? ? } else { \
? ? ? ? printf(":ok\n"); \
? ? ? ? ? ? ? ? }

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)與算法:單向鏈表實(shí)現(xiàn)與封裝

    數(shù)據(jù)結(jié)構(gòu)與算法:單向鏈表實(shí)現(xiàn)與封裝

    今天小編就為大家分享一篇關(guān)于數(shù)據(jù)結(jié)構(gòu)與算法:單向鏈表實(shí)現(xiàn)與封裝,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的掃雷小游戲

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的掃雷小游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • C語(yǔ)言實(shí)現(xiàn)打印數(shù)組以及打印注意事項(xiàng)說(shuō)明

    C語(yǔ)言實(shí)現(xiàn)打印數(shù)組以及打印注意事項(xiàng)說(shuō)明

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)打印數(shù)組以及打印注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • QT判斷兩個(gè)日期時(shí)間的大小

    QT判斷兩個(gè)日期時(shí)間的大小

    本文主要介紹了QT判斷兩個(gè)日期時(shí)間的大小,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • C++ 實(shí)現(xiàn)優(yōu)先隊(duì)列的簡(jiǎn)單實(shí)例

    C++ 實(shí)現(xiàn)優(yōu)先隊(duì)列的簡(jiǎn)單實(shí)例

    這篇文章主要介紹了C++ 實(shí)現(xiàn)優(yōu)先隊(duì)列的簡(jiǎn)單實(shí)例的相關(guān)資料,希望通過(guò)本文能幫助大家實(shí)現(xiàn)優(yōu)先隊(duì)列,需要的朋友可以參考下
    2017-08-08
  • VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法

    VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法

    本文主要介紹了VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • C++關(guān)于字符的接收與輸出操作示例

    C++關(guān)于字符的接收與輸出操作示例

    這篇文章主要介紹了C++關(guān)于字符的接收與輸出操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-01-01
  • C++中I/O模型之select模型實(shí)例

    C++中I/O模型之select模型實(shí)例

    這篇文章主要介紹了C++中I/O模型的select模型,實(shí)例講述了I/O模型的用法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-10-10
  • C++嵌入式內(nèi)存管理詳情

    C++嵌入式內(nèi)存管理詳情

    這篇文章主要介紹了C++嵌入式內(nèi)存管理,是對(duì)上一篇內(nèi)存的一個(gè)補(bǔ)充,主要講解Linux中的內(nèi)存;這部分對(duì)于一些端側(cè)部署的伙伴來(lái)說(shuō)比較重要,推薦針對(duì)不同的板子,下面來(lái)看看詳細(xì)內(nèi)容吧,需要的朋友可以參考一下
    2021-12-12
  • C++實(shí)現(xiàn)STL迭代器萃取的示例代碼

    C++實(shí)現(xiàn)STL迭代器萃取的示例代碼

    迭代器是一種抽象的設(shè)計(jì)概念,它提供了一種方法,使之能夠依序巡訪某個(gè)聚合物(容器)所含的各個(gè)元素,而又無(wú)需暴露該聚合物的內(nèi)部表述方式。本文主要介了STL迭代器萃取的方法,需要的可以參考一下
    2022-11-11

最新評(píng)論