调用C-函数时,可以通过传递可以转换/提升为更宽类型的窄类型来调用更宽的类型。
例如:
void FooBar(uint32_t alpha); // Function takes a 32-bit unsigned value
int main(void)
{
uint16_t foo = 232; // Variable foo is 16-bit unsigned
FooBar(foo); // 16-bit value gets auto-promoted to 32-bit value for the function call.
}然而,当我尝试用_Generic in C11来做这件事时,自动促销似乎已经失去了:
#define FooBar(x) _Generic((x), uint32_t: FooBar_U32,\
double: FooBar_DBL)(x)
int main(void)
{
uint16_t foo = 232; // Variable foo is 16-bit unsigned
FooBar(foo); // Try to promote a 16-bit to 32-bit value for FooBar_U32
float nib = 3.14;
FooBar(nib); // Try to promote a float to a double for FooBar_DBL
}错误是:
prog.c:7:28: error: ‘_Generic’ selector of type ‘short unsigned int’ is not compatible with any association我当然希望short unsigned int与unsigned int (32位)兼容。所以我不明白错误信息。
是否不可能使用_Generic并获得类型推广的好处?
我在这里做错什么了吗?
发布于 2022-06-27 21:15:02
这在语言规范定义的意义上是“兼容”的,而不是在定义自动转换或适用整数提升的类型对的更广泛意义上。相关的bits分布在规范的几个部分,包括至少6.2.7节(“兼容类型和复合类型”)、6.7.2节(“类型说明符”)、6.7.3节(“类型限定符”)和6.7.6节(“装配符”)。但是,对于枚举类型以外的算术类型,“兼容类型”简单地归结为相同类型,包括类型限定符。
这是非常严格的。例如,对于通过不同类型的lvalue访问某一类型的对象,严格的混叠规则所要求的情况更多。比跨赋值类型匹配或将函数参数匹配到相应参数所需的情况要多得多。不,short unsigned int在这个意义上与unsigned int不兼容,甚至在两种类型大小相同的实现中也不兼容。
是否不可能使用
_Generic并获得类型推广的好处?
您得到了lvalue转换,它删除了类型限定符,但是泛型关联不在应用“常规算术转换”的地方,在赋值和函数调用的上下文中执行的自动转换也不适用于此上下文(它们在应用的语言规范中显式调用)。
这种细粒度的方法是有意的.关键是泛型关联能够区分除其他外,与分配兼容的情况。例如,
#define hton(x) _Generic((x), uint32_t: htonl, uint16_t: htons)(x)我在这里做错什么了吗?
您的代码不符合语言规范。可以通过为每个相关类型定义泛型关联和/或将泛型选择的操作数类型转换为提供关联的类型之一来修复它。
这样做的方法之一是将泛型选择中的表达式更改为通常的算术转换(与泛型选择本身的转换相反),这一点在关于这个问题的评论中已经描述过了。但请注意,通常的算术转换比赋值转换要窄。另外,这在您的特定情况下可能没有用,因为uint32_t和uint16_t的整数提升(作为通常算术转换的一部分)不一定兼容。前者很可能是unsigned int,而后者是int。
https://stackoverflow.com/questions/72777977
复制相似问题