最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2022年11月14日 08:50:27   作者:englyf  
當年學習C語言的第一門課就提到過標記(Token)的概念,不過,相信在多年之后你再次聽到這個術(shù)語時會一臉懵逼,比如我。因此特地翻了翻資料,整理下來這些筆記,希望對大家有所幫助

當年學習C語言的第一門課就提到過標記(Token)的概念,不過,相信在多年之后你再次聽到這個術(shù)語時會一臉懵逼,比如我。

因此特地翻了翻資料,整理下來這些筆記。

在C語言中什么是標記

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

下面舉例說明一下:

printf("hello world!");

對上面的語句進行標記劃分,可分為5個標記,如下:

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

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

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

#字符串化操作符

用途是,將標記(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

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

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

##標記(Token)連接操作符

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

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

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

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

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

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

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

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

##還有個特殊的用途

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

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

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

但是,在宏定義時,如果直接使用__VA_ARGS__來引用可變參數(shù),一旦可變參數(shù)為空就會引起編譯器報錯,看看下面的例子

#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...");
      |   ^~~~~~~~

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

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

相關(guān)文章

  • 利用反射獲得類的public static/const成員的值實例

    利用反射獲得類的public static/const成員的值實例

    下面小編就為大家?guī)硪黄梅瓷浍@得類的public static/const成員的值實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • 詳解C++函數(shù)類型與重載函數(shù)

    詳解C++函數(shù)類型與重載函數(shù)

    這篇文章主要為大家介紹了C++函數(shù)類型與重載函數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • string居然也可以用<<和>>

    string居然也可以用<<和>>

    今天小編就為大家分享一篇關(guān)于string居然也可以用<<和>>,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • C++ Boost Chrono實現(xiàn)計時碼表流程詳解

    C++ Boost Chrono實現(xiàn)計時碼表流程詳解

    Boost是為C++語言標準庫提供擴展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標準庫的后備,是C++標準化進程的開發(fā)引擎之一,是為C++語言標準庫提供擴展的一些C++程序庫的總稱
    2022-11-11
  • C語言實現(xiàn)BMP圖像閉運算處理

    C語言實現(xiàn)BMP圖像閉運算處理

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)BMP圖像閉運算處理,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C++實現(xiàn)的泛型List類分享

    C++實現(xiàn)的泛型List類分享

    這篇文章主要介紹了C++實現(xiàn)的泛型List類分享,參考C#的List功能實現(xiàn),需要的朋友可以參考下
    2014-07-07
  • C++中如何實現(xiàn)SSL/TLS加密通信

    C++中如何實現(xiàn)SSL/TLS加密通信

    在互聯(lián)網(wǎng)時代,確保信息傳輸過程中的機密性、完整性和可用性成為了開發(fā)者必須考慮的關(guān)鍵因素,在C++網(wǎng)絡(luò)編程中,使用SSL/TLS加密通信是一種常見的做法,它允許客戶端和服務(wù)器之間通過互聯(lián)網(wǎng)安全地交換信息,從而為網(wǎng)絡(luò)通信提供隱私性和數(shù)據(jù)完整性
    2025-01-01
  • c++特殊構(gòu)造函數(shù)詳解

    c++特殊構(gòu)造函數(shù)詳解

    大家好,本篇文章主要講的是c++特殊構(gòu)造函數(shù)詳解,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • 獲取一個文件行數(shù)的方法

    獲取一個文件行數(shù)的方法

    獲取一個文件行數(shù)的方法,需要的朋友可以參考一下
    2013-03-03
  • C++設(shè)計模式之享元模式(Flyweight)

    C++設(shè)計模式之享元模式(Flyweight)

    這篇文章主要為大家詳細介紹了C++設(shè)計模式之享元模式Flyweight,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04

最新評論

彰化县| 六安市| 铁岭县| 唐海县| 贺州市| 随州市| 闵行区| 济宁市| 金昌市| 平湖市| 涡阳县| 小金县| 桐城市| 都江堰市| 通道| 轮台县| 安仁县| 湟源县| 高台县| 泗洪县| 丹棱县| 新营市| 岗巴县| 遂平县| 邵武市| 东城区| 衡水市| 盐城市| 宿迁市| 台南市| 密云县| 云南省| 蓝山县| 定兴县| 瑞金市| 永嘉县| 商洛市| 瑞昌市| 两当县| 磐安县| 江口县|