为什么长 l = 0x80000000是正数?
Why is long l = 0x80000000 a positive number?
在C++中,为什么long l = 0x80000000;
是正的?
C++:
long l = 0x80000000; // l is positive. Why??
int i = 0x80000000;
long l = i; // l is negative
根据这个网站:https://en.cppreference.com/w/cpp/language/integer_literal,0x80000000应该是一个有符号的int,但它似乎不是这样,因为当它被分配给l符号扩展时不会发生。
Java:
long l = 0x80000000; // l is negative
int i = 0x80000000;
long l = i; // l is negative
另一方面,Java具有更一致的行为。
C++ 测试代码:
#include <stdio.h>
#include <string.h>
void print_sign(long l) {
if (l < 0) {
printf("Negativen");
} else if (l > 0) {
printf("Positiven");
} else {
printf("Zeron");
}
}
int main() {
long l = -0x80000000;
print_sign(l); // Positive
long l2 = 0x80000000;
print_sign(l2); // Positive
int i = 0x80000000;
long l3 = i;
print_sign(l3); // Negative
int i2 = -0x80000000;
long l4 = i2;
print_sign(l4); // Negative
}
从您的链接:"整数文本的类型是值可以容纳的第一种类型,来自类型列表,这取决于使用了哪个数字基数和哪个整数后缀。 对于十六进制值,列出整数,无符号整数...
编译器使用 32 位整数,因此最大(有符号(整数为 0x7FFFFFFF。已签名的 int 不能表示0x8000000的原因...0xFFFFFFF是它需要其 32 位的 2^32 个可能值中的一些来表示负数。 但是,0x80000000适合 32 位无符号 int。您的编译器使用 64 位长整型,最多可容纳 0x7FFF FFFF FFFF FFFF,因此0x80000000也适合有符号长整型,因此长l
是正值0x80000000。
另一方面,inti
是一个有符号的 int,根本不适合0x80000000,因此会发生未定义的行为。当有符号数太大而无法放入C++时,经常发生的情况是使用双补运算并且数字四舍五入为一个大的负数。(不要依赖这种行为;众所周知,优化会打破这种行为(。无论如何,在这种情况下,两者的补体行为似乎确实发生了,导致i
是负面的。
在示例代码中,您同时使用 0x80000000 和 -0x80000000,在每种情况下,它们都有相同的结果。事实上,它们是一样的。回想一下,0x8000000是一个无符号的 int。2003 C++标准在 5.3.1c7 中说:"无符号量的负数是通过从 2^n 中减去其值来计算的,其中 n 是提升操作数中的位数。 0x80000000正好是 2^31,因此 -0x80000000 是 2^32-2^31=2^31。为了获得预期的行为,我们必须使用 -(long(0x80000000 代替。
在SO上很棒的人的帮助下,我想我现在可以回答我自己的问题了:
只是为了纠正0x80000000
不能放入整数的概念: 可以在没有丢失或未定义行为的情况下存储0x80000000
到int
的值(假设sizeof(int) == 4
(。下面的代码可以演示此行为:
#include <limits.h>
#include <stdio.h>
int main() {
int i = INT_MIN;
printf("%Xn", i);
return 0;
}
不过,将文字0x80000000
分配给变量并不微妙。
其他人(除了@Daniel Langr(没有提到的是C++没有否定文字的概念。
没有负整数文本。
-1
等表达式将一元减号运算符应用于文本表示的值,这可能涉及隐式类型转换。
考虑到这一点,文字0x80000000
始终被视为正数。否定是在确定大小和符号之后进行的。这很重要:否定不会影响文字的无符号/有符号,只有基数和值会影响。0x80000000
太大而无法容纳有符号整数,因此C++尝试使用下一个适用的类型:unsigned int
,然后成功。C++尝试的类型顺序取决于文字的基础以及它可能有或没有的任何后缀。
下表列出如下:https://en.cppreference.com/w/cpp/language/integer_literal
因此,考虑到这条规则,让我们制定一些示例:
-2147483648
: 被视为long int
,因为它不适合int
。2147483648
:被视为long int
,因为C++不认为unsigned int
是十进制文字的候选者。0x80000000
:被视为unsigned int
,因为C++认为unsigned int
是非十进制文字的候选者。(-2147483647 - 1)
: 被视为int
。这通常是定义INT_MIN
以将文本的类型保留为int
的方式。这是将-2147483648
作为int
的类型安全方式。-0x80000000
: 即使存在否定,也被视为unsigned int
。但是,否定任何unsigned
都是未定义的行为。-0x80000000l
: 被视为long int
,符号被正确否定。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 为什么在全局范围内使用"extern int a"似乎不行?
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 为什么会发生堆损坏
- 为什么使用 "this" 指针调用派生成员函数?
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 为什么比较运算符如此快速
- 为什么 Serial.println(<char[]>);返回随机字符?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 为什么不;名字在地图上是按顺序排列的吗
- 我的字符计数代码计算错误.为什么
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 为什么长 l = 0x80000000是正数?
- 为什么 1 不大于 -0x80000000
- 为什么ifstream读取0x80000000 int失败?
- 为什么我不能使用 '0x80000000' 来初始化 int 数组?