溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C語言中帶返回值的宏定義方式是什么

發(fā)布時間:2023-02-25 09:40:49 來源:億速云 閱讀:118 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“C語言中帶返回值的宏定義方式是什么”,在日常操作中,相信很多人在C語言中帶返回值的宏定義方式是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C語言中帶返回值的宏定義方式是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

C語言中帶返回值的宏定義

相信大家在實際工作中,一定有遇到需要編寫一個宏定義,且希望它能帶返回值的場景吧?

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

宏定義編寫

直接上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;
}

宏定義分析

為了分析宏定義的寫法,我們得知道宏定義最終被展開是什么樣的。

我在之前的博文中有提到,使用gcc編譯器的話,可以在CFLAGS上加上-save-temps=obj這個編譯選項,這樣就可以得到預(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文件我們可以看到,宏定義被正常展開,下面確認下功能是否正常。

宏定義驗證

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

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

驗證成功。

經(jīng)驗總結(jié)

  • 在C語言里面,可以使用({aaa; bbb; ccc;})來實現(xiàn)宏定義帶返回值;這里的返回值是最后一個;的值。

  • 注意里面的()和{}都不能少,否則可能會破壞代碼的語法結(jié)構(gòu),導(dǎo)致得不到正確的答案。

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

typeof 關(guān)鍵字

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

其實這個特性在 C 語言中也早有類似的實現(xiàn),GNU C 標準中的一個擴展特性 typeof 作用與 decltype 類似。

__typeof__ (ret) errnum = (ret);

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

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

【函數(shù)功能】:

先將可變參數(shù) “&hellip;” 按照format的格式格式化為字符串,然后再將其拷貝至dest_str中。

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

__builtin_expect的作用

__builtin_expect(errnum != 0, 0)

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

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

一般的使用方法是將__builtin_expect指令封裝為LIKELY和UNLIKELY宏。

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

  • __LINE__:當(dāng)前程序行的行號,表示為十進制整型常量

  • __FILE__:當(dāng)前源文件名,表示字符串型常量

  • __DATE__:轉(zhuǎn)換的日歷日期,表示為Mmm dd yyyy 形式的字符串常量,Mmm是由asctime產(chǎn)生的。

  • __TIME__:轉(zhuǎn)換的時間,表示"hh:mm:ss"形式的字符串型常量,是有asctime產(chǎn)生的。(asctime貌似是指的一個函數(shù))

  • __STDC__:編輯器為ISO兼容實現(xiàn)時位十進制整型常量

  • __func__:它指示所在的函數(shù)

  • __assert_perror_fail:打印一條包含錯誤碼ERRNUM的錯誤消息,并終止程序

反斜杠的作用

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

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

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

到此,關(guān)于“C語言中帶返回值的宏定義方式是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI