C++ C++;底流和溢流
嗨,我是新来的,所以如果有什么不对劲,请告诉我,下次我会努力做得更好 我试图理解C++中的下溢和溢出是如何工作的。我的理解是,如果变量超出了范围,它将从范围的另一端开始。因此,如果short的最小值是-32768,并且如果我们对它执行-1,那么新值应该是SHRT_MAX。(32767) 这是我的密码:C++ C++;底流和溢流,c++,C++,嗨,我是新来的,所以如果有什么不对劲,请告诉我,下次我会努力做得更好 我试图理解C++中的下溢和溢出是如何工作的。我的理解是,如果变量超出了范围,它将从范围的另一端开始。因此,如果short的最小值是-32768,并且如果我们对它执行-1,那么新值应该是SHRT_MAX。(32767) 这是我的密码: #include<iostream.h> #include<limits.h> #include<conio.h> int main ( void ) { i
#include<iostream.h>
#include<limits.h>
#include<conio.h>
int main ( void )
{
int testpositive =INT_MIN ;
short testnegative = SHRT_MIN ;
cout<< SHRT_MIN<<"\n";
cout << testnegative-1<<"\n";
cout << INT_MIN << "\n";
cout << testpositive-1 << "\n";
cout<<testpositive-2;
getch();
return 0;
}
#包括
#包括
#包括
内部主(空)
{
int testpositive=int_MIN;
短测试负=SHRT_MIN;
CUT通常是。但是由于这是C++,C++是由C++标准来调节的,所以必须知道溢出是<强>未定义的行为< /强> ./P>
虽然您所说的可能适用于大多数平台,但它不能保证,所以不要依赖它。<新的值不需要是代码> StTyxMax < /CUL>它是未定义的。< /P> < P>溢出/下溢的精确行为只针对<代码>未签名< /C> >类型。对于普通符号整数类型,C++标准只是简单地说。比任何事情都可能发生
如果我们谈论的是x86处理器(或大多数其他现代处理器),那么行为确实与您所描述的完全相同,对于CPU来说,有符号值和无符号值之间没有区别(有符号和无符号操作,但值本身只是位)
请注意,编译器可以假设(大多数现代优化编译器实际上都假设)在正确的程序中不会发生有符号整数溢出,例如在以下代码中:
int do_something();
int do_something_else();
void foo() {
int x = do_something();
int y = x + 1;
if (x < y) {
do_something();
} else {
do_something_else();
}
}
您可以看到,ODE只调用了<代码> dothOuts<代码>两次(除了C++的奇怪处理> RAX),并且没有提到 doyOththIGONEON/COD> >,或多或少是由代码> Gcc生成的相同代码。
< P>符号溢出是C++中的未定义行为。
例如:
INT\u MIN-1
-INT\u MIN
是调用未定义行为的表达式
SHRT\u MIN-1
和-SHRT\u MIN
在具有16位short
和32位int
的环境中不是未定义的行为,因为在整数提升中,操作数首先提升为int
。在具有16位short
和int
的环境中,这些表达式也是未定义的D行为。< /P>首先,该程序是很难定义的。程序可以很好地被销毁。操作数首先被提升到<代码> int >代码>,所以没有溢出。考虑将结果返回到短,看看你希望什么。惊奇。它工作了,现在我明白了。考虑使用<代码>包含< <代码> >代替<代码> >包含< /代码>。事情是MO。dern编译器利用签名溢出是未定义的行为来执行优化。因此,即使在CPU级别定义了该行为,也不能保证您的程序不会调用未定义的行为。@ouah:是的…添加了一个关于编译器在分析代码签名溢出是未定义的行为时可以自由执行的假设的注释。@b埃哈维
foo(): # @foo()
push rax
call do_something()
pop rax
jmp do_something() # TAILCALL