在C和c++中,什么是未定义的行为(UB) ?未指定的行为和实现定义的行为呢?它们之间的区别是什么?
当前回答
c++标准n3337§1.3.10 实现定义的行为
行为,对于结构良好的程序构造和正确的数据,即 这取决于实现和每个实现文档
有时候c++标准并没有把特定的行为强加给某些结构,而是说一个特定的、定义良好的行为必须由特定的实现(库的版本)选择和描述。所以用户仍然可以确切地知道程序的行为,即使标准没有描述这一点。
c++标准n3337§1.3.24 未定义的行为
behavior for which this International Standard imposes no requirements [ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. — end note ]
当程序遇到不是根据c++标准定义的构造时,它可以做任何它想做的事情(可能给我发一封电子邮件,也可能给你发一封电子邮件,或者可能完全忽略代码)。
c++标准n3337§1.3.25 未指明的行为
行为,对于结构良好的程序构造和正确的数据,即 依赖于实现[注:实现不是 需要记录发生的行为。可能的范围 行为通常是由本国际标准来描述的。- - -结束 请注意)
c++标准没有将特定的行为强加于某些结构,而是说特定的、定义良好的行为必须由特定的实现(库的版本)选择(bot没有必要描述)。因此,在没有提供描述的情况下,用户很难确切地知道程序将如何运行。
其他回答
好吧,这基本上是直接从标准复制粘贴
3.4.1 1 implementation-defined behavior unspecified behavior where each implementation documents how the choice is made 2 EXAMPLE An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right. 3.4.3 1 undefined behavior behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements 2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). 3 EXAMPLE An example of undefined behavior is the behavior on integer overflow. 3.4.4 1 unspecified behavior use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance 2 EXAMPLE An example of unspecified behavior is the order in which the arguments to a function are evaluated.
未定义行为vs.未指定行为有一个简短的描述。
他们最后的总结是:
总而言之,未指定的行为通常是不应该发生的 担心,除非你的软件被要求是可移植的。 相反,未定义的行为总是不受欢迎的,也不应该这样做 发生。
c++标准n3337§1.3.10 实现定义的行为
行为,对于结构良好的程序构造和正确的数据,即 这取决于实现和每个实现文档
有时候c++标准并没有把特定的行为强加给某些结构,而是说一个特定的、定义良好的行为必须由特定的实现(库的版本)选择和描述。所以用户仍然可以确切地知道程序的行为,即使标准没有描述这一点。
c++标准n3337§1.3.24 未定义的行为
behavior for which this International Standard imposes no requirements [ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. — end note ]
当程序遇到不是根据c++标准定义的构造时,它可以做任何它想做的事情(可能给我发一封电子邮件,也可能给你发一封电子邮件,或者可能完全忽略代码)。
c++标准n3337§1.3.25 未指明的行为
行为,对于结构良好的程序构造和正确的数据,即 依赖于实现[注:实现不是 需要记录发生的行为。可能的范围 行为通常是由本国际标准来描述的。- - -结束 请注意)
c++标准没有将特定的行为强加于某些结构,而是说特定的、定义良好的行为必须由特定的实现(库的版本)选择(bot没有必要描述)。因此,在没有提供描述的情况下,用户很难确切地知道程序将如何运行。
实现定义的,
实现者希望,应该有良好的文档,标准给出了选择,但一定要编译
未指定的,
与实现定义的相同,但没有文档化
未定义的,
不管发生什么事,都要小心。
也许简单的措辞比严格的标准定义更容易理解。
实现定义的行为: 语言说我们有数据类型。编译器供应商指定了他们应该使用的大小,并提供了他们所做的工作的文档。
未定义的行为: 你做错了什么。例如,int型中有一个非常大的值,但不适合char型。如何将该值放入char?其实没有办法!任何事情都可能发生,但最明智的做法是将int的第一个字节放入char类型。这样做分配第一个字节是错误的,但这是在引擎盖下发生的事情。
未指明的行为: 这两个函数哪个先执行?
void fun(int n, int m);
int fun1() {
std::cout << "fun1";
return 1;
}
int fun2() {
std::cout << "fun2";
return 2;
}
//...
fun(fun1(), fun2()); // which one is executed first?
语言没有指定计算值,从左到右还是从右到左!因此,未指定的行为可能会导致未定义的行为,也可能不会导致未定义的行为,但可以肯定的是,您的程序不应该产生未指定的行为。
@eSKay我认为你的问题值得编辑答案以澄清更多:)
For fun(fun1(), fun2());行为不是“实现定义的”吗?编译器必须选择一个或另一个过程,毕竟?
The difference between implementation-defined and unspecified, is that the compiler is supposed to pick a behavior in the first case but it doesn't have to in the second case. For example, an implementation must have one and only one definition of sizeof(int). So, it can't say that sizeof(int) is 4 for some portion of the program and 8 for others. Unlike unspecified behavior, where the compiler can say: "OK I am gonna evaluate these arguments left-to-right and the next function's arguments are evaluated right-to-left." It can happen in the same program, that's why it is called unspecified. In fact, C++ could have been made easier if some of the unspecified behaviors were specified. Take a look here at Dr. Stroustrup's answer for that:
It is claimed that the difference between what can be produced giving the compiler this freedom and requiring "ordinary left-to-right evaluation" can be significant. I'm unconvinced, but with innumerable compilers "out there" taking advantage of the freedom and some people passionately defending that freedom, a change would be difficult and could take decades to penetrate to the distant corners of the C and C++ worlds. I am disappointed that not all compilers warn against code such as ++i+i++. Similarly, the order of evaluation of arguments is unspecified. IMO far too many "things" are left undefined, unspecified, that's easy to say and even to give examples of, but hard to fix. It should also be noted that it is not all that difficult to avoid most of the problems and produce portable code.
推荐文章
- 为什么STL如此严重地基于模板而不是继承?
- 查找当前可执行文件的路径,不包含/proc/self/exe
- 未定义对静态constexpr char的引用[]
- 在c++中,restrict关键字是什么意思?
- 如何创建可变参数宏(参数数量可变)
- c++中类似于java的instanceof
- include_directories和target_include_directories在CMake中的区别是什么?
- std::make_pair与std::pair的构造函数的目的是什么?
- 如何追加一个字符到std::字符串?
- 为什么C语言这么快,为什么其他语言没有这么快或更快?
- 转发C中可变函数的调用
- 为什么要在c++中使用嵌套类?
- 如何处理11000行c++源文件?
- 使用g++编译多个.cpp和.h文件
- 当尝试用const初始化变量时,错误“初始化元素不是常量”