C可变宽度位域

Bra*_*est 3 c gcc struct

我在这里不会问很多问题,所以请原谅我,如果我的"提问技巧"有点生疏了.开始:


我环顾四周,似乎无法找到解决方案.

这个想法是程序打印出一个具有任意位大小的数字的每个可能值的十进制(有符号和无符号),十六进制和二进制表示.它接受来自argv的位大小,并且示例输出应该是(关注二进制表示):

$ ./test 2
00
01
10
11
$ ./test 4
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Run Code Online (Sandbox Code Playgroud)

如果我使用预处理器宏,这可以正常工作,但这意味着我每次想要更改位大小时都必须重新编译.如果不是一个小小的警告,Argv会解决我所有的问题.这就是编译器不喜欢我想要做的事情,即使它看起来很合乎逻辑.

我想要做的是这样的:

int bit_size = atoi(argv[1]);
struct { unsigned int a : bit_size; } test;
Run Code Online (Sandbox Code Playgroud)

但编译器给了我一个错误,非常严厉地告诉我我不能这样做("位域不是整数常量").

好的...所以我尝试使用一个const int代替:

const int bit_size = atoi(argv[1]);
struct { unsigned int a : bit_size; } test;
Run Code Online (Sandbox Code Playgroud)

我得到了同样的错误.

需要注意的是:GCC 希望我做的是:

struct { unsigned int a : 8; } test;
Run Code Online (Sandbox Code Playgroud)

它没有任何问题.但我需要能够改变这一点.

我很困惑.

请注意,我不希望或需要位域的宽度能够改变中间程序,这是我假设GCC试图阻止我做的.这实际上是一次性操作.

另请注意,我并不是想在像这个问题这样的普通变量上做这个(还有很多其他喜欢它).

这个问题也与我想要完成的事情无关.


此外,如果它有帮助,这是一个在没有错误的情况下运行时显示的示例(位域宽度= 4):

$ ./test 4
$ cat table.md
Table for a/an 4-bit integer: 

| Unsigned | Signed | Hex | Binary | Sign Bit |
|:--------:|:------:|:---:|:------:|:--------:|
|    0     |   0    |  0  |  0000  |    0     |
|    1     |   1    |  1  |  0001  |    0     |
|    2     |   2    |  2  |  0010  |    0     |
|    3     |   3    |  3  |  0011  |    0     |
|    4     |   4    |  4  |  0100  |    0     |
|    5     |   5    |  5  |  0101  |    0     |
|    6     |   6    |  6  |  0110  |    0     |
|    7     |   7    |  7  |  0111  |    0     |
|    8     |   -8   |  8  |  1000  |    1     |
|    9     |   -7   |  9  |  1001  |    1     |
|    10    |   -6   |  A  |  1010  |    1     |
|    11    |   -5   |  B  |  1011  |    1     |
|    12    |   -4   |  C  |  1100  |    1     |
|    13    |   -3   |  D  |  1101  |    1     |
|    14    |   -2   |  E  |  1110  |    1     |
|    15    |   -1   |  F  |  1111  |    1     |
Run Code Online (Sandbox Code Playgroud)

Éti*_*nne 5

您无法在C中以运行时定义位字段的大小.但是您不需要位字段来打印二进制值,只需编写一个函数来打印二进制格式的数字,如下所示: 是否有printf转换器以二进制格式打印?

然后写一个简单的循环来打印你的数字:

//get n
for (int i = 0; i < n; i++) {
    print_binary(i);
}
Run Code Online (Sandbox Code Playgroud)

编辑:回答你关于打印用二进制补码编码的负数的问题,这些数字在C中没有本机类型(如int8_t,int16_t,int32_t ..),就像你发现在2的补码中用N位编码的有符号字一样,对于负数,您可以使用相等:

Xnegative = 2 ^ N - X阳性

//get n
for (uint32_t Xpos = 0; Xpos < (1<<n); Xpos++) {
    if (Xpos > 1<<(n-1))
        printf("%d\n", -(1 << n) + Xpos);
    else
        printf("%u\n", Xpos);
}
Run Code Online (Sandbox Code Playgroud)