为什么 unsigned typeof(var) 不起作用? const typeof(x) 工作正常,为什么不呢?

问题描述

在宏中,我希望使值具有相同的宽度,但无符号。因此,自然而然地想到了 unsigned typeof(x)。但是,它不会编译:

/home/guest/mc.c: In function ‘main’:
/home/guest/mc.c:14:36: error: expected ‘)’ before ‘typeof’
   14 |                         *((unsigned typeof(minus)*)&minus));

我想知道为什么会这样?也许我做错了什么?我可以以某种方式将 unsigned 添加到变量的类型吗?

附注。我注意到,类似的演员添加 const 工作正常:

#define add_const(x) ((const typeof(x))(x))

此外,添加 * 来创建指针类型也可以。

解决方法

看起来唯一的方法是在泛型选择中枚举所有“有趣”的类型。

#define to_unsigned(x) _Generic((x),\
                char: (unsigned char     )(x),\
         signed char: (unsigned char     )(x),\
                 int: (unsigned int      )(x),\
               short: (unsigned short    )(x),\
                long: (unsigned long     )(x),\
           long long: (unsigned long long)(x),\
             default: x)

short a;
typeof(to_unsigned(a)) ua;

这不是可移植的,因为实现可以提供更多的整数类型。然而 typeof 本身是特定于 gcc 的。由于 gcc 似乎提供所有其他标准整数类型(size_tuint8_t 等)作为 typedef 名称而不是单独的不同类型,因此这些情况应该涵盖所有内容。

,

为什么 unsigned typeof(var) 不起作用? const typeof(x) 工作正常,为什么不呢?

每个clause 6.7 of the GCC 10.2 documentation

typeof 构造可用于任何可以使用 typedef 名称的地方。

在 C 2018 6.7 中指定的声明的 C 语法中,声明说明符被划分为类:

  • 存储类说明符,例如 staticextern
  • 类型说明符,例如 intfloat
  • 类型限定符,例如 constvolatile
  • 函数说明符,例如 inline
  • 对齐说明符,例如 _Alignas(4)

第 6.7.2 条表明 typedef-name 是一个类型说明符。第 2 段规定了它们的使用方式。它给出了允许的组合列表,包括:

  • intsignedsigned int
  • unsignedunsigned int
  • typedef 名称

因此,unsigned 只能用于此列表中显示的特定组合,例如 unsigned long long。 typedef 名称本身显示为一个项目,没有 unsigned。因此它不能与 unsigned 一起使用。

相比之下,const是一个限定符,它是一种不同种类的说明符,6.7的其他条款允许不同种类的说明符混合使用(有一些额外的限制在这里不相关,例如最多有一个存储类说明符)。

,

unsigned typeof(x) 不起作用而 const typeof(x) 起作用的根本原因是 unsignedconst 是两个不同的语法组件。 unsigned 是类型说明符,而 const 是类型限定符。

类型说明符列表(请注意,裸 unsigned 在语法上等同于 unsigned int

6.7.2 Type specifiers

1. 语法

      type-specifier:
             void
             char
             short
             int
             long
             float
             double
             signed
             unsigned
             _Bool
             _Complex
             atomic-type-specifier
             struct-or-union-specifier
             enum-specifier
             typedef-name

2. 约束

...

  • 无符号或无符号整数

所以 unsigned typeof(x) 相当于 unsigned int typeof(x)

const 是一个类型限定符:

6.7.3 Type qualifiers

1. 语法

      type-qualifier:
             const
             restrict
             volatile
             _Atomic

const char 是正确的 C 代码,假设 xcharunsigned int char 不是正确的 C 代码。