我知道C++ 中的"未定义行为"几乎可以让编译器做任何想做的事情.但是,我遇到了让我感到惊讶的崩溃,因为我认为代码足够安全.
在这种情况下,真正的问题仅发生在使用特定编译器的特定平台上,并且仅在启用了优化时才发生.
我尝试了几件事来重现问题并将其简化到最大程度.这是一个名为的函数的摘录Serialize,它将获取bool参数,并将字符串true或复制false到现有的目标缓冲区.
如果bool参数是未初始化的值,那么这个函数是否会在代码审查中,没有办法告诉它实际上可能会崩溃?
// Zero-filled global buffer of 16 characters
char destBuffer[16];
void Serialize(bool boolValue) {
// Determine which string to print based on boolValue
const char* whichString = boolValue ? "true" : "false";
// Compute the length of the string we selected
const size_t len = strlen(whichString);
// Copy string into destination buffer, which is zero-filled (thus already null-terminated)
memcpy(destBuffer, whichString, len);
}
Run Code Online (Sandbox Code Playgroud)
如果使用clang 5.0.0 +优化执行此代码,它将/可能崩溃.
boolValue ? "true" …
如果我有:
unsigned int x;
x -= x;
Run Code Online (Sandbox Code Playgroud)
很明显,x 应该这样表达后是零,但到处看,他们说的行为,这种代码是不确定的,而不是仅仅值x(直到减法之前).
两个问题:
这段代码的行为确实未定义吗?
(例如,代码在兼容系统上崩溃[或更糟]?)
如果是这样,为什么 C表示行为是未定义的,当非常清楚x这里应该为零时?
即不在此定义行为给出的优势是什么?
很明显,编译器可以简单地使用它在变量中认为"方便"的任何垃圾值,并且它可以按预期工作......这种方法有什么问题?
在以下代码中,变量没有初始值并打印此变量.
int var;
cout << var << endl;
Run Code Online (Sandbox Code Playgroud)
输出:2514932
double var;
cout << var << endl;
Run Code Online (Sandbox Code Playgroud)
输出:1.23769e-307
我不明白这些输出数字.任何人都可以向我解释一下吗?
我检查过自己,我写了一个这样的程序
int main() {
int i;
cout << i;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我运行了几次程序,结果一直都是一样的,零.我在C中尝试过,结果是一样的.
但我的教科书说
如果不初始化在函数内定义的变量,则变量值保持未定义.这意味着该元素将采用先前驻留在内存中该位置的任何值.
当程序总是为变量分配空闲内存位置时,这怎么可能?怎么可能是零以外的东西(我假设默认的空闲内存值为零)?
我需要初始化一个向量以用作缓冲区。在将内容放入其中之前,我不关心它包含什么值,因此我不希望程序浪费时间用零填充它。我知道with_capacity,但它需要我push()元素,这很不方便,因为我需要不断检查我之前是否已将某些内容推送到索引。
基本上,我正在寻找与此 C++ 数组等效的数组:
int* arr = new int[size];
arr[2]; // random garbage
Run Code Online (Sandbox Code Playgroud) 我在VisualStudio2010中玩c ++
请解释IT发生的原因:
int a, b;
int *p, *q;
cout << a << " " << b;
Run Code Online (Sandbox Code Playgroud)
打印出"0 0".嗯,这是可以理解的,未初始化的整数应为0; 但
int a, b;
int *p, *q;
p = &a;
cout << a << " " << b;
Run Code Online (Sandbox Code Playgroud)
输出为"1792816880 0"
因此,如果我将指针指定给未初始化的变量,则会更改默认值.为什么?
编辑澄清:问题不是关于未初始化变量的值
int a; int *p;
cout << a; // would be 0, because it's loacal variable
p = &a;
cout << a; //not 0;
Run Code Online (Sandbox Code Playgroud)
如何获得的指针一个可以改变它的价值?当我们初始化变量时,我们分配空间,一些位,它们可以是任何东西,但"p =&a"它实际上是否改变了这个空间中的位?
int main()
{
int a;
cout << a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想知道为什么要输出值 0。我想如果一个变量未初始化,它会输出一个垃圾值。
但是,我也记得听说整数的默认值是 0,所以我有点困惑。
谢谢
考虑以下代码:
#include <stdio.h>
int main()
{
char A = A ? 0[&A] & !A : A^A;
putchar(A);
}
Run Code Online (Sandbox Code Playgroud)
我想问一下,是否观察到任何未定义的行为.
编辑
请注意:代码故意使用0[&A] & !A和NOT A & !A(请参阅下面的回复)
结束编辑
从g ++ 6.3(https://godbolt.org/g/4db6uO)获取输出ASM 得到(没有使用优化):
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov BYTE PTR [rbp-1], 0
movzx eax, BYTE PTR [rbp-1]
movsx eax, al
mov edi, eax
call putchar
mov eax, 0
leave
ret
Run Code Online (Sandbox Code Playgroud)
然而clang为同一件事提供了更多的代码(没有再次优化):
main: # @main
push rbp
mov rbp, rsp
sub rsp, 16 …Run Code Online (Sandbox Code Playgroud) 出于某种原因, 的值为final_sum16 但我没有为该变量初始化值,这是为什么呢?不是应该开始0吗?
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
int n, sum, final_sum;
cout<<"ff: "<<final_sum<<endl;
cout<<"Input the value for n: ";
cin>>n;
for(int i=1; i<=n; i++){
sum += i;
final_sum += sum;
cout<<"sum: "<<sum<<endl;
cout<<"final sum: "<<final_sum<<endl<<endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud) 读取未初始化的变量会导致未定义的行为,例如
#include <iostream>
int main()
{
int a;
std::cout << a << std::endl; // undefined behavior
}
Run Code Online (Sandbox Code Playgroud)
有人可以对这个事实给出正式的解释吗?
#include <iostream>
using namespace std;
int main()
{
int a;
int b;
cout<<a<<endl;
cout<<b;
}
Run Code Online (Sandbox Code Playgroud)
为什么我编译这个时 b 有 16 个值?我不明白为什么 b 有 16 而不是 0。Int 没有 0 作为默认值?