我在这里问的问题不多,所以如果我的“提问技巧”有点生疏,请原谅我。开始了:
我环顾四周,似乎找不到解决办法。
这个想法是程序打印出一个表,其中包含具有任意位大小的数字的每个可能值的十进制(有符号和无符号)、十六进制和二进制表示形式。它接受来自 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
如果我使用预处理器宏,这会很好地工作,但这意味着每次我想更改位大小时都必须重新编译。如果不是因为一个小警告,Argv 将解决我所有的问题。那就是编译器不喜欢我正在尝试做的事情,即使它看起来完全合乎逻辑。
我想做的是:
int bit_size = atoi(argv[1]);
struct { unsigned int a : bit_size; } test;
但是编译器给我一个错误,非常严厉地告诉我我不能那样做(“bitfield not an integer constant”)。
好吧...所以我尝试使用 const int
代替:
const int bit_size = atoi(argv[1]);
struct { unsigned int a : bit_size; } test;
我得到了完全相同的错误。
请注意:GCC 要我做的是:
struct { unsigned int a : 8; } test;
而且它没有任何问题。但我需要能够改变它。
我很困惑。
请注意,我不希望或不需要位域的宽度能够在程序中更改,这是我假设 GCC 试图阻止我做的事情。这实际上是一次操作。
另请注意,我并没有尝试对像 this question 这样的普通变量执行此操作(还有许多其他人喜欢它)。
This question也与我想要完成的事情无关。
另外,如果有帮助的话,这是一个无错误运行时显示的示例(位域宽度 = 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 |
最佳答案
您不能在运行时在 C 中定义位字段的大小。但是您不需要位字段来打印二进制值,只需编写一个函数来打印二进制格式的数字,例如一个在这里: Is there a printf converter to print in binary format?
然后写一个简单的循环来打印你的数字:
//get n
for (int i = 0; i < n; i++) {
print_binary(i);
}
编辑: 要回答有关打印以二进制补码编码的负数的问题,这些负数在 C 中没有 native 类型(如 int8_t、int16_t、int32_t..),就像您发现在 2 的补码中编码为 N 位的有符号字一样,对于负数您可以使用相等的数字:
Xnegative = 2^N - Xpositive
//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);
}
关于C可变宽度位域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23160614/