C/C++培训
达内IT学院
400-996-5531
编程中有时会遇到一些有歧义的表达式,比如 a[i] = i++ 。那么 a[i] = i++ 到底对不对呢?
首先请看如下代码:
#include<stdio.h>
int main(){
int i=0;
int a[3] = {1,2,3};
a[i] = i++;
printf("%d \n",a[i]);
printf("%d %d %d ",a[0],a[1],a[2]);
return 0;
}
对于这个表达式中 a[i] = i++,子表达式i++有一个副作用,它会改变i的值,由于i在同一表达式中会被引用,因此这样会导致未定义的行为。因为无法判定该引用(该公式中的左边的a[i]中)是新值还是旧值。
不同的编译器在解释此类行为的时候会有不同的理解,比如下面三个编译器(dev c++ 、 codeblocks、vs2019 )对于上述的代码就有不同的理解。
对于此类行为,尽管有些文献中认为这类表达式的行为是不确定的,但是c标准却强烈声明它是未定义的。
未定义行为的其他示例包括访问超出其边界的数组, 解除引用空指针, 在生命终结后访问对象 或写作 据称聪明的表达 喜欢 i++ + ++i。
未定义的行为还有两个不那么危险的兄弟, 不确定的行为 和 实现定义的行为。
那么实现定义的行为、不确定的行为、未定义的行为这三者的区别在哪里呢?
首先这三种情况都代表了c语言标准中没有明确要求某个特定构造或使用它的程序必须完成的事情的领域。c语言定义中的这种松散性是传统的,但是这种规定方式是经过深思熟虑的,这种定义方式允许作者:
1 选择某些构造可以按照“硬件完成的方式”生成高效的代码。
2 忽略某些太难准确定义、并且可能在良好书写的程序中没什么实际用处的边界构造。
对于这3种“标准中没有准确定义的行为“的定义如下:
1 实现定义的行为
抽象机的某些方面和操作在本国际标准中描述为 实现定义 (例如, sizeof(int))。这些构成了抽象机器的参数。每个实施应包括描述其在这些方面的特征和行为的文件。
2 不确定的行为
抽象机的某些其他方面和操作在本国际标准中描述为 不明 (例如,评估函数参数的顺序)。在可能的情况下,C语言国际标准定义了一组允许的行为。这些定义了抽象机器的非确定性方面。
3 未定义的行为
任何事情都有可能发生,标准对此没有任何要求,程序可能编译失败、运行错误(直接崩溃或者生成错误的结果)或者幸运的如程序员所愿。
既然标准对编译器没有进行任何要求,那么编译器就可以做出任何可能的行为。在程序中忍受未定义的想法是极其危险的,未定义行为比你想象的还要未定义。
如果大家想书写可移植代码,那么上述的三种行为都是需要极力避免的。因此我们在编写代码时最好避免 a[i] = i++ 这种C语言未定义的写法。
版权声明:转载文章来自公开网络,版权归作者本人所有,推送文章除非无法确认,我们都会注明作者和来源。如果出处有误或侵犯到原作者权益,请与我们联系删除或授权事宜。
填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!
Copyright © 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有
Tedu.cn All Rights Reserved