什么是 C 中未定义的行为?
我正在使用 GCC 编译器。在某些情况下,尽管程序的输出应该是未定义的,但我得到了正确的值。我多次运行这些程序。但结果是一致的。对于其他一些程序,结果是不确定的。那么,在哪些情况下我应该考虑程序行为真的是未定义的?有什么规则吗?
什么是 C 中未定义的行为?
我正在使用 GCC 编译器。在某些情况下,尽管程序的输出应该是未定义的,但我得到了正确的值。我多次运行这些程序。但结果是一致的。对于其他一些程序,结果是不确定的。那么,在哪些情况下我应该考虑程序行为真的是未定义的?有什么规则吗?
未定义行为的定义:
C11(ISO/IEC 9899:201x)§3.4.3
1 未定义的行为
行为,在使用不可移植或错误程序结构或错误数据时,本国际标准对此没有要求
2 注 可能的未定义行为范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特征的记录方式表现(有或没有发出诊断消息),到终止翻译或执行(有发出诊断消息)。
3 示例 未定义行为的一个示例是整数溢出行为。
C11 §J.2 中还有一个未定义行为列表未定义行为
未定义的行为意味着编译器可以发出它喜欢的任何代码。您的程序可能会显示您期望的结果,或者它可能会格式化您的硬盘驱动器,或者它可以开始向塔利班发送电子邮件。任何事情都可能发生
这可以通过一个例子来说明,
#include "stdio.h"
int *ptr;
void func2()
{
int k = 300;
}
void func1()
{
int t = 100;
ptr = &t;
}
int main(int argc, char *argv)
{
func1();
printf("The value of t=%d\r\n",*ptr);
func2();
printf("The value of t=%d\r\n",*ptr);
}
On my machine, I got the following.
joshis1@(none) temp]$ ./ud.out
The value of t=100
The value of t=300
这说明 t 的值没有得到保证。一旦 t 的范围结束,堆栈空间就分配给 k。因此, ptr 正在访问相同的地址 - 内存位置。但是变量范围已经结束。如果您不调用 func2(); ,您将获得一致的结果;因此,编译器不保证结果 -> 这称为未定义行为。
我认为,简而言之,如果不能保证指令的行为在所有编译器或所有情况下都保持一致,则可以将其称为未定义行为。