簡體   English   中英

gcc -E不擴展C11 _Generic表達式

[英]gcc -E does not expand C11 _Generic expressions

在C11庫項目中,我有一些使用泛型在共享宏名稱下公開的宏函​​數,如下所示:

#define signum(operand) _Generic( (operand),    \
    unsigned long long:  __signum_i4, unsigned long:  __signum_i3, unsigned int:  __signum_i2, unsigned short: __signum_i1, unsigned char: __signum_i0,     \
    signed long long:    __signum_i4, signed long:    __signum_i3, signed int:    __signum_i2, signed short:   __signum_i1, signed char:   __signum_i0, \
    long double:         __signum_f2, double:         __signum_f1, float:         __signum_f0,  \
    complex long double: __signum_c2, complex double: __signum_c1, complex float: __signum_c0   \
) (operand)

它們似乎運行良好,但出於分析原因,我想為某些測試用例創建預處理源,以便我可以驗證編譯器是否選擇了預期的泛型替換。 但是,當使用gcc -EI獲得半擴展輸出時,如下所示:

 assert(_Generic( (0LL), unsigned long long: __signum_i4, unsigned long: __signum_i3, unsigned int: __signum_i2, unsigned short: __signum_i1, unsigned char: __signum_i0, signed long long: __signum_i4, signed long: __signum_i3, signed int: __signum_i2, signed short: __signum_i1, signed char: __signum_i0, long double: __signum_f2, double: __signum_f1, float: __signum_f0, _Complex long double: __signum_c2, _Complex double: __signum_c1, _Complex float: __signum_c0 ) (0LL) == 0);
 assert(_Generic( (+1LL), unsigned long long: __signum_i4, unsigned long: __signum_i3, unsigned int: __signum_i2, unsigned short: __signum_i1, unsigned char: __signum_i0, signed long long: __signum_i4, signed long: __signum_i3, signed int: __signum_i2, signed short: __signum_i1, signed char: __signum_i0, long double: __signum_f2, double: __signum_f1, float: __signum_f0, _Complex long double: __signum_c2, _Complex double: __signum_c1, _Complex float: __signum_c0 ) (+1LL) == +1);
 ...

我假設_Generic是一個預處理器功能,因此期望通用宏像這樣完全展開:

assert(__signum_i4(0LL) == 0);
assert(__signum_i4(+1LL) == +1);
assert(__signum_i4(-1LL) == -1);
...

有沒有辦法用gcc標志來實現這個目的?

我假設_Generic是一個預處理器功能

實際上,正如C11草案中所描述的那樣,它不是primary-expression (如identifierstring literal )。 所以它由C編譯器而不是預處理器處理。

關於問題的第二部分:

有沒有辦法用gcc標志來實現這個目的?

您可以轉儲GIMPLE樹,這是解析C之后的中間表示,它將為您提供接近您正在尋找的內容:

#include <math.h>
#include <stdio.h>
#define cbrt(X) _Generic((X), long double: cbrtl, \
                              default: cbrt, \
                              float: cbrtf)(X)

int main(void)
{
    long double a = 0.0;
    printf("%e\n", cbrt(a));
    return 0;
}

然后:

$ gcc -c -fdump-tree-gimple main.c

結果如下:

main ()
{
  long double D.3241;
  int D.3242;
  long double a;

  a = 0.0;
  D.3241 = cbrtl (a);
  printf ("%e\n", D.3241);
  D.3242 = 0;
  return D.3242;
}

_Generic(C11,6.5.1.1)顯然需要有關控制表達式類型的信息。 這顯然只是由編譯器提供,而不是由預處理器提供。 所以它是編譯器的一部分(6.5.1 - primary-expression)。

我有點想知道為什么這被稱為預處理器功能(不只是由你,但可能是網站!)。 我想,因為它在宏中是有意義的,就像在普通函數中一樣,類型已經是已知的。

旁注(與顯示的代碼無關,但很重要): 關聯列表中可能只有一種兼容類型 它不會區分 - 例如 - inttypdef int MyInt; const int (實際上只允許最多一個,6.5.1.1/constraint 2)。

我假設_Generic是一個預處理器功能......

事實並非如此。 它被視為一個運算符 ,並在C11標准的第6.5.1.1節中有記錄。第6.5.1節指出泛型選擇是一種主表達式

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM