我在这里不问很多问题,所以如果我的“提问技巧”有点生疏,请原谅我。开始:
我环顾四周,似乎无法找到解决方案。
这个想法是程序打印出一个包含任意位大小的数字的每个可能值的十进制(有符号和无符号)、十六进制和二进制表示的表格。它接受来自 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;
但是编译器给了我一个错误,非常严厉地告诉我我不能这样做(“位域不是整数常量”)。
好的...所以我尝试使用
const int
代替:const int bit_size = atoi(argv[1]);
struct { unsigned int a : bit_size; } test;
我得到相同的确切错误。
请注意:海湾合作委员会希望我做的是:
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/