C和C++中未定义,未指定和实现定义的行为有什么区别?
c c++ undefined-behavior unspecified-behavior implementation-defined-behavior
我今天刚上课了 - 阅读C代码和输入,如果程序实际运行,所需答案就是屏幕上显示的内容.其中一个问题被声明a[4][4]为一个全局变量,并且在该程序的一个点上,它试图访问a[27][27],所以我回答了类似" 访问一个超出其边界的数组是一个未定义的行为 ",但老师说它a[27][27]的值将为0.
之后,我尝试了一些代码来检查"所有未初始化的golbal变量是否设置为0"是否为真.好吧,这似乎是真的.
所以现在我的问题是:
a[27][27]是0所有环境?编辑:
在该代码中,a[4][4]是唯一声明的全局变量,并且还有一些更多本地变量main().
我在DevC++中再次尝试了该代码.所有这些都是0.但在VSE中并非如此,其中大多数值都是,0但有些值具有Vyktor指出的随机值.
常量0用作C和C++中的空指针.但随着问题"指向一个特定的固定地址 "似乎有一些可能使用分配固定地址.在任何系统中,对于访问地址0的任何低级任务,是否有任何可能的需求?
如果有,那怎么解决0为空指针而全部?
如果没有,是什么让它确定没有这种需要?
我偶然发现了以下代码片段:
#include <iostream>
#include <string>
using namespace std;
class First
{
string *s;
public:
First() { s = new string("Text");}
~First() { delete s;}
void Print(){ cout<<*s;}
};
int main()
{
First FirstObject;
FirstObject.Print();
FirstObject.~First();
}
Run Code Online (Sandbox Code Playgroud)
该文本表示此代码段应该导致运行时错误.现在,我对此并不十分肯定,所以我尝试编译并运行它.有效.奇怪的是,尽管所涉及的数据非常简单,但在打印"文本"之后程序结结巴巴,并且仅在一秒钟之后完成.
我添加了一个要打印到析构函数的字符串,因为我不确定显式调用这样的析构函数是否合法.程序打印两次字符串.所以我的猜测是析构函数被调用两次,因为正常的程序终止不知道显式调用并试图再次销毁对象.
一个简单的搜索确认显式调用自动化对象上的析构函数是危险的,因为第二次调用(当对象超出范围时)具有未定义的行为.所以我很幸运,我的编译器(VS 2017)或这个特定的程序.
关于运行时错误,文本是否完全错误?或者运行时错误真的很常见吗?或者也许我的编译器实现了某种针对这类事情的warding机制?
c++ destructor lifetime undefined-behavior explicit-destructor-call
在最近的一个问题中,有人提到当使用printf打印指针值时,调用者必须将指针强制转换为void*,如下所示:
int *my_ptr = ....
printf("My pointer is: %p", (void *)my_ptr);
Run Code Online (Sandbox Code Playgroud)
对于我的生活,我无法弄清楚为什么.我发现了这个问题,几乎是一样的.问题的答案是正确的 - 它解释了整数和指针的长度不一定相同.
这是当然的,真实的,但是当我已经在的情况下有一个指针,像上面,我为什么要由铸铁int *到void *?什么时候int*与void*不同?事实上,什么时候(void *)my_ptr生成任何与简单不同的机器代码my_ptr?
更新:多个知识渊博的响应者引用了标准,说传递错误的类型可能会导致未定义的行为.怎么样?我期望printf("%p", (int *)ptr)并printf("%p", (void *)ptr)生成完全相同的堆栈帧.两个调用何时生成不同的堆栈帧?
看看这段代码:
#include <iostream>
#include <string>
void foo(int(*f)()) {
std::cout << f() << std::endl;
}
void foo(std::string(*f)()) {
std::string s = f();
std::cout << s << std::endl;
}
int main() {
auto bar = [] () -> std::string {
return std::string("bla");
};
foo(bar);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用它编译
g++ -o test test.cpp -std=c++11
Run Code Online (Sandbox Code Playgroud)
导致:
bla
Run Code Online (Sandbox Code Playgroud)
喜欢它应该做的.用它编译
clang++ -o test test.cpp -std=c++11 -stdlib=libc++
Run Code Online (Sandbox Code Playgroud)
导致:
zsh: illegal hardware instruction ./test
Run Code Online (Sandbox Code Playgroud)
并用它编译
clang++ -o test test.cpp -std=c++11 -stdlib=stdlibc++
Run Code Online (Sandbox Code Playgroud)
还导致:
zsh: illegal hardware instruction ./test
Run Code Online (Sandbox Code Playgroud)
Clang/GCC版本: …
我正在尝试使用 GCC,试图说服它假设代码的某些部分无法访问,以便趁机进行优化。我的一项实验给了我一些奇怪的代码。这是来源:
#include <iostream>
#define UNREACHABLE {char* null=0; *null=0; return {};}
double test(double x)
{
if(x==-1) return -1;
else if(x==1) return 1;
UNREACHABLE;
}
int main()
{
std::cout << "Enter a number. Only +/- 1 is supported, otherwise I dunno what'll happen: ";
double x;
std::cin >> x;
std::cout << "Here's what I got: " << test(x) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
我是这样编译的:
g++ -std=c++11 test.cpp -O3 -march=native -S -masm=intel -Wall -Wextra
Run Code Online (Sandbox Code Playgroud)
函数的代码test如下所示:
_Z4testd:
.LFB1397:
.cfi_startproc
fld QWORD PTR [esp+4] …Run Code Online (Sandbox Code Playgroud)