【C進階】25、#和##運算子

bryson發表於2021-12-25

Summary

1)'#'用於在預處理期巨集引數轉換為字串只在巨集定義中有效編譯器不知道'#'的存在

2)可以使用#+函式名,在呼叫時列印函式名

3)'##'用於在預處理期 拼接兩個識別符號只在巨集定義中有效編譯器不知道'##'的存在

4)可以使用'##'快速定義結構體、使用結構體,快速定義類等。

·#和##運算子分析

1、'#'

  • '#'運算子用於在預處理期巨集引數轉換為字串(給引數加上雙引號);
  • '#'的轉換是在預處理期完成的,所以只在巨集定義中有效編譯器不知道'#'的轉換作用
  • 用法:

    #define STRING(s) #s
    printf("%s\n", STRING(hello world));
    
    單步編譯:gcc -E test.c -o test.i
    中間結果:printf("%s\n", "hello world");

可以使用#+函式名,在呼叫時把函式名列印出來

#define CALL(f, p) (printf("call function: %s\n", #f), f(p))

void func()
{
    printf("function output");
}

int main()
{
    CALL(f, 1);        // C語言中如果不寫引數列表,則接受任意多引數
    return 0;
}

2、'##'

  • '##'運算子用於在預處理期粘連兩個字元(拼接字元
  • '##'的拼接作用是在預處理期完成的,因此只在巨集定義中有效編譯器不知道'##'的拼接作用
  • 用法:

    #define CONNECT(a, b) a##b
    
    int CONNECR(a, 1);    // int a1;
    a1 = 2;

工程中可以用'##'快速定義結構體(定義不同的類等)

// 在C語言中使用結構體必須帶上struct關鍵字,就可以用下面的巨集封裝下typedef,
// 然後就可以把struct當成一個型別來用

#define STRUCT(type) typedef strtuct __tag_##type type; \
                        struct __tag_##type
STRTUCT(Student)
{
    char* name;
    int id;
};

int main()
{
    Student s;
    s.name = "ss";
    s.id = 1;

    printf("name: %s, id: %d\n"), s.name, s.id);
    retrun 0;
}

本文總結自“狄泰軟體學院”唐佐林老師《C語言進階課程》。
如有錯漏之處,懇請指正。

相關文章