【发布时间】:2014-04-18 19:09:24
【问题描述】:
我在这里问的问题不多,如果我的“提问技巧”有点生疏,请见谅。如下:
我环顾四周,似乎找不到解决办法。
这个想法是程序打印出一个包含任意位大小的数字的每个可能值的十进制(有符号和无符号)、十六进制和二进制表示形式的表格。它接受来自 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;
我得到了同样的错误。
请注意: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 没有这个。哦,
const限定对象不是 C 中的常量,它只是一个只读对象。 -
只需使用完整的无符号整数并将代码限制为特定宽度。
-
@ouah 我不知道“常量”和“只读”之间存在区别
-
啊哈,所以基本上,位域不是解决方案。我使用的唯一原因是有符号整数,但我只是注意到有符号负数中的逻辑模式(符号位 - 数字的其余部分 = 负数的绝对值)。稍后我可能会发布我自己的答案。
-
@Étienne 啊,所以这就是二进制补码是什么。