【发布时间】:2019-09-26 08:09:43
【问题描述】:
根据 C11 标准(在 this answer 中提到),该标准强制支持以下类型:_Bool、signed int 和 unsigned int。可以支持其他类型,但取决于实现。
我尝试按照代码查看实际中位域的类型:
#include <stdint.h>
#include <assert.h>
#include <stdio.h>
#define ARG_TYPE(arg) _Generic((arg), \
_Bool : "_Bool", \
char : "char", \
signed char : "signed char", \
unsigned char : "unsigned char", \
short : "short", \
unsigned short : "unsigned short", \
int : "int", \
unsigned int : "unsigned int", \
long : "long", \
unsigned long : "unsigned long", \
long long : "long long", \
unsigned long long : "unsigned long long")
int main(void)
{
struct _s
{
unsigned int uval32 : 32;
unsigned int uval16 : 16;
unsigned int uval8 : 8;
unsigned int uval1 : 1;
signed int ival32 : 32;
signed int ival16 : 16;
signed int ival8 : 8;
signed int ival1 : 1;
_Bool bool1 : 1;
} s = {0};
printf("The type of s.uval32 is %s\n", ARG_TYPE(s.uval32));
printf("The type of s.uval16 is %s\n", ARG_TYPE(s.uval16));
printf("The type of s.uval8 is %s\n", ARG_TYPE(s.uval8));
printf("The type of s.uval1 is %s\n", ARG_TYPE(s.uval1));
printf("The type of s.ival32 is %s\n", ARG_TYPE(s.ival32));
printf("The type of s.ival16 is %s\n", ARG_TYPE(s.ival16));
printf("The type of s.ival8 is %s\n", ARG_TYPE(s.ival8));
printf("The type of s.ival1 is %s\n", ARG_TYPE(s.ival1));
printf("The type of s.bool1 is %s\n", ARG_TYPE(s.bool1));
(void)s;
return 0;
}
Clang (https://godbolt.org/z/fjVRwI) 和 ICC (https://godbolt.org/z/yC_U8C) 的行为符合预期:
The type of s.uval32 is unsigned int
The type of s.uval16 is unsigned int
The type of s.uval8 is unsigned int
The type of s.uval1 is unsigned int
The type of s.ival32 is int
The type of s.ival16 is int
The type of s.ival8 is int
The type of s.ival1 is int
The type of s.bool1 is _Bool
但是 GCC (https://godbolt.org/z/FS89_b) 引入了几个问题:
-
_Bool以外定义的单个位域不适合_Generic中引入的任何类型:
错误:“unsigned char:1”类型的“_Generic”选择器不兼容 与任何关联
-
在注释掉发出错误的行后,我得到了这个:
The type of s.uval32 is unsigned int The type of s.uval16 is unsigned short The type of s.uval8 is unsigned char The type of s.ival32 is int The type of s.ival16 is short The type of s.ival8 is signed char The type of s.bool1 is _Bool对我来说,
unsigned short、short、unsigned char和signed char在这里完全出乎意料。
我误解了标准吗?这是 GCC 错误吗?
看起来像使用_Generic 即使对于定义明确的东西也不能移植......
【问题讨论】:
标签: c gcc types bit-fields c11