标准规定十六进制常量如0x8000(大于有符号整数)是无符号的(就像八进制常量一样),而像32768那样的十进制常量是长符号。 (确切类型假设一个16位整数和一个32位长。)但是,在常规C环境中,两者将具有相同的表示形式,二进制1000 0000 0000 0000
。
这种差异真的会产生不同的结果吗?换句话说,这种差异是否很重要?
答案 0 :(得分:7)
是的,这很重要。如果您的处理器具有16位int
和32位long
类型,则32768具有类型long
(因为32767是符合有符号16位的最大正值{ {1}}),而0x8000(因为它也被认为是int
)仍然适合16位unsigned int
。
现在考虑以下计划:
unsigned int
当32768被认为是int main(int argc, char *argv[])
{
volatile long long_dec = ((long)~32768);
volatile long long_hex = ((long)~0x8000);
return 0;
}
时,否定将反转32位,
导致表达式为0xFFFF7FFF,类型为long
;演员是
多余。
当0x8000被视为long
时,否定将反转
16位,产生类型unsigned int
的表示0x7FFF;
然后,强制转换将零扩展到unsigned int
值0x00007FFF。
请看H& S5,第27.1页第24页第24页。
最好根据需要使用long
,U
或UL
来增加常量。
答案 1 :(得分:1)
在具有64位long
的32位平台上,以下代码中的a
和b
将具有不同的值:
int x = 2;
long a = x * 0x80000000; /* multiplication done in unsigned -> 0 */
long b = x * 2147483648; /* multiplication done in long -> 0x100000000 */
答案 2 :(得分:1)
尚未给出的另一项检查:比较(大于或小于运算符)-1到32768和0x8000。或者,就此而言,尝试将它们中的每一个与等于-32768的'int'变量进行比较。
答案 3 :(得分:1)
假设int
是16位且long
是32位(这些天实际上相当不寻常; int
更常见的是32位):
printf("%ld\n", 32768); // prints "32768"
printf("%ld\n", 0x8000); // has undefined behavior
在大多数情况下,数值表达式将隐式转换为由上下文确定的适当类型。 (但这并不总是你想要的类型。)这不适用于变量函数的非固定参数,例如格式字符串后面的*printf()
函数之一的任何参数。
答案 4 :(得分:0)
不同之处在于,如果您尝试向16位int添加一个值,它将无法执行此操作,因为它会超出变量的边界,而如果您使用的是32位长,则可以添加任何值它的数量小于2 ^ 16。