C++:大型unsigned int的编译器警告

gru*_*czy 19 c++ int unsigned warnings

我有以下数组,我需要在位图上手动操作.

const unsigned int BITS[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 
                               2048, 4096, 8192, 16384, 32768, 65536, 131072, 
                               262144, 524288, 1048576, 2097152, 4194304, 
                               8388608, 16777216, 33554432, 67108864, 134217728, 
                               268435456, 536870912, 1073741824, 2147483648};
Run Code Online (Sandbox Code Playgroud)

不幸的是,编译时我得到了

警告:此十进制常量仅在ISO C90中无符号

我该如何删除?

Bro*_*ses 20

默认情况下,C中的整数文字类型为"signed int"(编辑:但请参阅警告的注释).最后一个数字太大而无法表示为带符号的32位整数,因此您需要告诉编译器它是无符号整数,后缀为"U",如:

2147483648U
Run Code Online (Sandbox Code Playgroud)

请注意,您还可以添加后缀"L"以使其为"long",但在许多系统上仍然是32位且因此无关紧要.

此外,使用位移运算符编写此代码的方法更容易出错(也更容易阅读):

const unsigned int BITS[32] = {1U, 1U<<1, 1U<<2, 1U<<3, 1U<<4,
                               /* and so on */
                               1U<<31};
Run Code Online (Sandbox Code Playgroud)

或者,如果你因为某些原因不喜欢位移,用十六进制写:

const unsigned int BITS[32] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20,
                               /* and so on */
                               0x80000000U};
Run Code Online (Sandbox Code Playgroud)

  • @gruszczy:在C89/90中,一个未加十进制的十进制常量必须解释为`int`,`long`或`unsigned long`(以先到者为准).在C99中,它必须被解释为`int`,`long`或`long long`(以先到者为准).这就是编译器试图通过此警告说的内容.显然,在这个平台上,`long`与`int`的大小相同.编译器基本上是在说:"也许你正在尝试创建一个`signed long`connstant或者甚至是一个`long long`常量,但是根据C89/90规则,我必须使它成为`unsigned long`. (3认同)
  • 事实上,情况有点复杂.它并不像"它总是签名int"那么容易:C90,C99和C++之间存在差异,并且对hex/oct和decimal文字有不同的处理方式.这一切都引起了很大的麻烦. (2认同)

Pie*_*ter 7

你的常量也必须被指定为无符号,使用

2147483648UL
Run Code Online (Sandbox Code Playgroud)

(UL =无符号长),或简单地说

2147483648U
Run Code Online (Sandbox Code Playgroud)

对于unsigned int.

由于您的代码现在是一个常量,默认情况下是一个普通的int,因而签名的,被分配给一个unsigned int生成警告的常量.

  • 谨慎地说,错误不是因为(plain int)常量被赋值给unsigned int; 作业无关紧要.该错误是因为"2147483648"的值太大而不能成为有符号的int,因此首先生成signed int常量会出现溢出. (3认同)
  • 实际上,警告的真正原因是编译器必须为常量类型选择`unsigned long`.(注意,这个常量不是`unsigned int`,它是`unsigned long`.)并且它必须在C89/90中特别选择它,而不是选择更大的签名类型(它可能支持)或者遵循C99规则和选择`long long`.这就是警告的内容以及它为何引用"ISO C90".例如,在C99中,永远不会给出未填充的十进制常量无符号类型. (2认同)