C/C++中的未定义行为

未定义行为(Undefined Behavior)

一些编程语言中,某些情况下存在未定义行为,以C和C++最为著名。在这些语言的标准中,规定某些操作的语义是未定义的,典型的例子就是程序错误的情况,比如越界访问数组元素。标准允许语言的具体实现做这样的假设:只要是匹配标准的程序代码,就不会出现任何类似的行为。具体到 C/C++ 中,编译器可以选择性地给出相应的诊断信息,但没有对此的强制要求:针对未定义行为,语言实现作出任何反应都是正确的,类似于数字逻辑中的无关项。
------百度百科

一句话总结: 未定义行为就是运行结果不确定

C和C++的未定义行为的一些例子

尝试修改字符串字面量会产生未定义行为
char * p = "wikipedia"; // C++11中错误,C++98/C++03不推荐使用
p[0] = 'W'; // 未定义行为

防止这一点的方法之一是将它定义为数组而不是指针:

char p[] = "wikipedia"; /* 正确 */
p[0] = 'W';

在C++可以使用[[标准模板库]]中的string类型,如下所示:

std::string s = "wikipedia"; /* 正确 */
s[0] = 'W';
除以零会导致未定义行为

根据IEEE 754,float、double和long double类型的值除以零的结果是无穷大或NaN:

return x/0; // 未定义行为
某些指针操作可能导致未定义行为
int arr[4] = {0, 1, 2, 3};
int* p = arr + 5;  // 未定义行为
到达返回数值的函数(除main函数以外)的结尾,而没有一个return语句,会导致未定义行为
int f()
  { }  /* 未定义行为 */

《C程序设计语言》在第2.12节引用下面的代码作为未定义行为的例子:

printf("%d %d\n", ++n, power(2, n));    /* 未定义行为 */

以及

a[i] = i++; /* 未定义行为 */
标准库可能指定未定义行为
int x = 1;
printf("%d\n", &x);    /*未定义行为:%d预期int类型的实际参数*/
printf("%p\n", &x);    /*未定义行为:%p预期void*类型的实际参数*/
printf("%p\n", (void*)&x); /*%p和void*类型的实际参数匹配,不在此引发未定义行为*/
一道例题

下列 C 代码中,不属于未定义行为的有:______。
A :int i=0;i=(i++);
B :char *p=”hello”;p[1]=’E’
C :char *p=”hello”;char ch=*p++
D :int i=0;printf(“%d%d\n”,i++,i–)
E :都是未定义行为
F :都不是未定义行为
正确答案: C

A选项,不知道编译器会怎么选择自增和赋值的顺序,所以这是由编译器决定的,属于未定义行为。
B选项,”hello“这个字符串属于一个字符串常量了,指针p指向了这个字符串常量,通过这个指针来直接修改常量第二个字符,这也属于未定义行为。
C选项,只是通过指针找到第二个字符并将它赋值给一个字符变量,并没有改变这个字符串常量,所以不属于未定义行为。
D选项,在printf语句中,i++和i–谁先执行由编译器决定,这是未定义行为。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值