为什么 unsigned typeof(var) 不起作用? const typeof(x) 工作正常,为什么不呢?
Why doesn't unsigned typeof(var) work? const typeof(x) works fine, so why not?
在宏中,我想让值具有相同的宽度,但是没有符号。于是,自然而然的想到了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
添加到变量类型吗?
PS。我注意到,添加 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_t
、uint8_t
等)作为 typedef 名称而不是单独的不同类型,因此这些情况应该涵盖所有内容。
unsigned typeof(x)
不起作用而 const typeof(x)
起作用的根本原因是 unsigned
和 const
是两个不同的语法组件。 unsigned
它是一个类型说明符,而 const
是一个类型限定符。
类型说明符列表(请注意,空 unsigned
在句法上等同于 unsigned int
:
1. Syntax
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. Constraints
...
- unsigned, or unsigned int
所以 unsigned typeof(x)
等价于 unsigned int typeof(x)
.
const
是类型限定符:
1. Syntax
type-qualifier:
const
restrict
volatile
_Atomic
const char
是正确的 C 代码,假设 x
是 char
。 unsigned int char
不是正确的 C 代码。
Why doesn't unsigned typeof(var) work? const typeof(x) works fine, so why not?
根据 clause 6.7 of the GCC 10.2 documentation:
A typeof
construct can be used anywhere a typedef name can be used.
在 C 2018 6.7 中指定的声明的 C 语法中,声明说明符被划分为 classes:
- Storage-class 说明符,例如
static
和 extern
.
- 类型说明符,例如
int
和 float
。
- 类型限定符,例如
const
和 volatile
。
- 函数说明符,例如
inline
.
- 对齐说明符,例如
_Alignas(4)
.
条款 6.7.2 表明 typedef-name 是一个类型说明符。第 2 段指定了它们的使用方式。它给出了允许组合的列表,包括:
int
、signed
或 signed int
unsigned
,或unsigned int
- typedef 名称
因此,unsigned
只能用于此列表中显示的特定组合,例如 unsigned long long
。 typedef 名称单独显示为一个项目,没有 unsigned
。所以它不能与 unsigned
.
一起使用
相比之下,const
是一个限定符,是一种不同的说明符,6.7的其他条款允许混合使用不同种类的说明符(有一些额外的限制在这里不相关,例如最多有一个存储-class 说明符)。
在宏中,我想让值具有相同的宽度,但是没有符号。于是,自然而然的想到了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
添加到变量类型吗?
PS。我注意到,添加 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_t
、uint8_t
等)作为 typedef 名称而不是单独的不同类型,因此这些情况应该涵盖所有内容。
unsigned typeof(x)
不起作用而 const typeof(x)
起作用的根本原因是 unsigned
和 const
是两个不同的语法组件。 unsigned
它是一个类型说明符,而 const
是一个类型限定符。
类型说明符列表(请注意,空 unsigned
在句法上等同于 unsigned int
:
1. Syntax
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. Constraints
...
- unsigned, or unsigned int
所以 unsigned typeof(x)
等价于 unsigned int typeof(x)
.
const
是类型限定符:
1. Syntax
type-qualifier: const restrict volatile _Atomic
const char
是正确的 C 代码,假设 x
是 char
。 unsigned int char
不是正确的 C 代码。
Why doesn't unsigned typeof(var) work? const typeof(x) works fine, so why not?
根据 clause 6.7 of the GCC 10.2 documentation:
A
typeof
construct can be used anywhere a typedef name can be used.
在 C 2018 6.7 中指定的声明的 C 语法中,声明说明符被划分为 classes:
- Storage-class 说明符,例如
static
和extern
. - 类型说明符,例如
int
和float
。 - 类型限定符,例如
const
和volatile
。 - 函数说明符,例如
inline
. - 对齐说明符,例如
_Alignas(4)
.
条款 6.7.2 表明 typedef-name 是一个类型说明符。第 2 段指定了它们的使用方式。它给出了允许组合的列表,包括:
int
、signed
或signed int
unsigned
,或unsigned int
- typedef 名称
因此,unsigned
只能用于此列表中显示的特定组合,例如 unsigned long long
。 typedef 名称单独显示为一个项目,没有 unsigned
。所以它不能与 unsigned
.
相比之下,const
是一个限定符,是一种不同的说明符,6.7的其他条款允许混合使用不同种类的说明符(有一些额外的限制在这里不相关,例如最多有一个存储-class 说明符)。