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

C語(yǔ)言冷知識(shí)之預(yù)處理字符串操作符詳解

 更新時(shí)間:2022年11月14日 08:50:27   作者:englyf  
當(dāng)年學(xué)習(xí)C語(yǔ)言的第一門(mén)課就提到過(guò)標(biāo)記(Token)的概念,不過(guò),相信在多年之后你再次聽(tīng)到這個(gè)術(shù)語(yǔ)時(shí)會(huì)一臉懵逼,比如我。因此特地翻了翻資料,整理下來(lái)這些筆記,希望對(duì)大家有所幫助

當(dāng)年學(xué)習(xí)C語(yǔ)言的第一門(mén)課就提到過(guò)標(biāo)記(Token)的概念,不過(guò),相信在多年之后你再次聽(tīng)到這個(gè)術(shù)語(yǔ)時(shí)會(huì)一臉懵逼,比如我。

因此特地翻了翻資料,整理下來(lái)這些筆記。

在C語(yǔ)言中什么是標(biāo)記

標(biāo)記是編程語(yǔ)言處理的基本單元,也叫最小劃分元素,比如關(guān)鍵字、操作符、變量名、函數(shù)名、字符串、數(shù)值等等。

下面舉例說(shuō)明一下:

printf("hello world!");

對(duì)上面的語(yǔ)句進(jìn)行標(biāo)記劃分,可分為5個(gè)標(biāo)記,如下:

printf              // 函數(shù)名
(                   // 左小括號(hào)操作符
"hello world!"      // 字符串
)                   // 右小括號(hào)操作符
;                   // 分號(hào)

預(yù)處理字符串操作符

在C語(yǔ)言中,預(yù)處理字符串操作符有兩個(gè),###。

#字符串化操作符

用途是,將標(biāo)記(Token)轉(zhuǎn)成字符串。

Syntax:

#define TOKEN_NAME(param) #param

Basic Usage:

#include <stdio.h>

#define MACRO_NAME(param)  #param

int main()
{
    printf(MACRO_NAME(hello world));

    return 0;
}

Output:

hello world

在項(xiàng)目實(shí)踐中,用宏定義的值的同時(shí)也需要將宏名轉(zhuǎn)成字符串使用,對(duì)日志的輸出尤其管用。

Best Practice:

#include <stdio.h>

#define NAME(param)  #param

#define LEN_MAX     10

int main()
{
    int array[LEN_MAX] = {0};
    int index = 10;
    if (index >= LEN_MAX) {
        printf("error: %s:%d is over %s:%d\n", NAME(index), index, NAME(LEN_MAX), LEN_MAX);
    } else {
        printf("read %s[%d]=%d\n", NAME(array), index, array[index]);
    }

    return 0;
}

Output:

error: index:15 is over LEN_MAX:10

如果修改如下:

int index = 9;

Output:

read array[9]=0

##標(biāo)記(Token)連接操作符

用途是,將##前后的標(biāo)記(Token)串接成新的單一標(biāo)記。

syntax:

#define TOKEN_CONCATENATE(param1, param2) param1##param

Basic Usage:

#include <stdio.h>

#define TOKEN_CONCATENATE(param1, param2) param1##param2

int main()
{
    printf("%d\n", TOKEN_CONCATENATE(12, 34));

    return 0;
}

Output:

1234

通常,編碼實(shí)踐中,代碼中會(huì)出現(xiàn)一些書(shū)寫(xiě)看上去雷同的片段,極其啰嗦冗余。為了壓縮源碼篇幅,可以參考代碼生成器的思想,在預(yù)編譯階段用宏定義代碼片段展開(kāi)替換,同時(shí)根據(jù)輸入的參數(shù)用##組合各種標(biāo)記。

假設(shè)有個(gè)需求是聲明定義一組同一類(lèi)型的結(jié)構(gòu)體的變量,并初始化其內(nèi)部成員。既然聲明定義的這些變量屬于同一類(lèi)型的結(jié)構(gòu)體,那么按照直接編碼的方式,就會(huì)有多次重復(fù)的代碼片段出現(xiàn),里邊包括了聲明定義語(yǔ)句,以及初始化各個(gè)成員的語(yǔ)句,不同的只是變量名或者參數(shù)而已。

舉個(gè)栗子,下面基于同一類(lèi)型的結(jié)構(gòu)體,聲明定義兩個(gè)變量,并初始化,看代碼

#include <stdio.h>
#include <string.h>

#define NAME(param)     #param

typedef struct {
    char *data;
    int   data_size;  /* number of byte real */
    int   max_size;   /* maximnm data size.*/
} my_type;

#define my_type_create(name, size) \
    char name ## _ ## data[size] = {0}; \
    my_type name; \
    memset(&name, 0x00, sizeof(name)); \
    name.data = name ## _ ## data; \
    name.max_size = size; \
    printf("variable name=%s\nmember data=%s, data_size=%d, max_size=%d\n", \
            NAME(name), NAME(name ## _ ## data), name.data_size, name.max_size); \

int main() {
    my_type_create(var1, 10)
    my_type_create(var2, 20)
}

上面的代碼中,定義了宏my_type_create,內(nèi)部實(shí)現(xiàn)了結(jié)構(gòu)體變量的聲明定義,以及內(nèi)部成員的初始化。如果按照直接編碼的方式,代碼量相對(duì)于上面的代碼量會(huì)虛增n-1倍,n=變量的個(gè)數(shù)。

在main函數(shù)中,調(diào)用宏的時(shí)候輸入?yún)?shù)var和10,那么在編譯預(yù)處理階段,根據(jù)輸入的參數(shù),宏my_type_create會(huì)展開(kāi)為以下的代碼段。

char var_data[10] = {0}; \
my_type var; \
memset(&var, 0x00, sizeof(var)); \
var.data = var_data; \
var.max_size = 10; \
printf("variable name=%s\nmember data=%s, data_size=%d, max_size=%d", \
        “var”, var_data, var.data_size, var.max_size); \

Output:

variable name=var1
member data=var1_data, data_size=0, max_size=10
variable name=var2
member data=var2_data, data_size=0, max_size=20

##還有個(gè)特殊的用途

在宏定義中,也支持用...代表可變參數(shù)。

#define MY_PRINT(fmt, ...) printf(fmt, __VA_ARGS__)

由于可變參數(shù)數(shù)目不確定,所以沒(méi)有具體的標(biāo)記。于是為了引用可變參數(shù),語(yǔ)言層面提供了可變宏(Variadic macros)__VA_ARGS__來(lái)引用它。

但是,在宏定義時(shí),如果直接使用__VA_ARGS__來(lái)引用可變參數(shù),一旦可變參數(shù)為空就會(huì)引起編譯器報(bào)錯(cuò),看看下面的例子

#include <stdio.h>

#define LOG_INFO(fmt, ...) printf("[I]" fmt "\n", __VA_ARGS__)

int main() {
  LOG_INFO("info...");
  LOG_INFO("%s, %s", "Hello", "world");
}

Output:

main.c: In function ‘main’:
main.c:3:62: error: expected expression before ‘)’ token
    3 | #define LOG_INFO(fmt, ...) printf("[I]" fmt "\n", __VA_ARGS__)
      |                                                              ^
main.c:6:3: note: in expansion of macro ‘LOG_INFO’
    6 |   LOG_INFO("info...");
      |   ^~~~~~~~

為了解決上面的問(wèn)題,在__VA_ARGS__前面添加上##,這樣的目的是告訴預(yù)處理器,如果可變參數(shù)為空,那么前面緊跟者的逗號(hào),在宏定義展開(kāi)時(shí)會(huì)被清理掉。

到此這篇關(guān)于C語(yǔ)言冷知識(shí)之預(yù)處理字符串操作符詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言預(yù)處理字符串操作符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言中的數(shù)據(jù)整除判斷問(wèn)題

    C語(yǔ)言中的數(shù)據(jù)整除判斷問(wèn)題

    這篇文章主要介紹了C語(yǔ)言中的數(shù)據(jù)整除判斷問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 奇怪的C語(yǔ)言特性

    奇怪的C語(yǔ)言特性

    下面列出的特性未必奇怪,有的算是有趣
    2013-04-04
  • C++與C語(yǔ)言的區(qū)別你知道嗎

    C++與C語(yǔ)言的區(qū)別你知道嗎

    這篇文章主要為大家詳細(xì)介紹了C++與C的區(qū)別,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • C語(yǔ)言面試C++字符串替換空格示例

    C語(yǔ)言面試C++字符串替換空格示例

    這篇文章主要介紹了C語(yǔ)言面試中C++字符串替換空格示例,文中給出了基本上可以拿下offer的代碼,有需要的朋友可以借鑒參考下,希望大家都能早日拿到心儀的offer
    2021-09-09
  • C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問(wèn)題詳解

    C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問(wèn)題詳解

    c++?vector轉(zhuǎn)數(shù)組是一種將vector容器的元素轉(zhuǎn)換為數(shù)組的方法,主要能幫助提高程序的性能和效率,下面這篇文章主要給大家介紹了關(guān)于C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問(wèn)題的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • C++面試八股文之位運(yùn)算問(wèn)題詳解

    C++面試八股文之位運(yùn)算問(wèn)題詳解

    這篇文章主要為大家介紹了C++面試八股文之位運(yùn)算的問(wèn)題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • C++使用extern實(shí)現(xiàn)源文件變量與類(lèi)成員函數(shù)的巧妙共享

    C++使用extern實(shí)現(xiàn)源文件變量與類(lèi)成員函數(shù)的巧妙共享

    C++中使用extern關(guān)鍵字可實(shí)現(xiàn)在源文件之間共享變量與類(lèi)成員函數(shù),通過(guò)聲明變量或類(lèi)在頭文件中,再在一個(gè)源文件中定義,其他源文件通過(guò)extern引用,促使模塊化、可維護(hù)的代碼組織,這篇文章主要介紹了C++用extern實(shí)現(xiàn)源文件變量與類(lèi)成員函數(shù)的巧妙共享,需要的朋友可以參考下
    2024-03-03
  • C++標(biāo)準(zhǔn)庫(kù)封裝的vector數(shù)組

    C++標(biāo)準(zhǔn)庫(kù)封裝的vector數(shù)組

    這篇文章主要介紹了C++標(biāo)準(zhǔn)庫(kù)封裝的vector數(shù)組,vector創(chuàng)建的對(duì)象包含眾多封裝好的函數(shù),想了解其相關(guān)資料的小伙伴可以參考下面文章內(nèi)容,希望對(duì)你的學(xué)習(xí)有所幫助
    2022-03-03
  • C語(yǔ)言遞歸函數(shù)與漢諾塔問(wèn)題簡(jiǎn)明理解

    C語(yǔ)言遞歸函數(shù)與漢諾塔問(wèn)題簡(jiǎn)明理解

    遞歸(recursive)函數(shù)是“自己調(diào)用自己”的函數(shù),無(wú)論是采用直接或間接調(diào)用方式。間接遞歸意味著函數(shù)調(diào)用另一個(gè)函數(shù)(然后可能又調(diào)用第三個(gè)函數(shù)等),最后又調(diào)用第一個(gè)函數(shù)。因?yàn)楹瘮?shù)不可以一直不停地調(diào)用自己,所以遞歸函數(shù)一定具備結(jié)束條件
    2022-07-07
  • CRITICAL_SECTION用法案例詳解

    CRITICAL_SECTION用法案例詳解

    這篇文章主要介紹了CRITICAL_SECTION用法案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08

最新評(píng)論