返回信息流C/C++里面有一些“未定义行为”,是不是指没有在官方标准(比如C99、C11)里定义的行为?那么官方标准为什么不定义这些行为?
“未定义行为”又叫依赖机器相关的行为,比如求余操作中余数的符号等等,那么这种操作依赖的是机器的什么部分?是处理器?操作系统?内存?IDE?还是别的什么?
谢谢
这是一条镜像帖。来源:北邮人论坛 / cpp / #88696同步于 2015/9/21
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
请问依赖机器的行为,依赖的是机器的什么部分
lywzx
2015/9/21镜像同步14 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
可以去搜一下 undefined,unspecified 和 implementation-defined 的区别
其中 undefined 和 unspecified 是不应该在程序中出现的
implementation-defined 是不同实现可能有区别的,所以移植性会有问题
当然如果你要研究黑科技可能就要经常和这些打交道了
有时候,世界上,人们对于某个东西没有共识。
比如很早以前,机器的一个“字节”(byte)有多少个“比特”(bit),没有共识,有的是8,有的是10,有的是5,或者是别的什么大小,所以c也没有规定
就算到了80年代,人们对“IEEE754”浮点数也没有达成共识,富士通的一些计算机有自己的浮点数表示法。
所以C语言也不好规定哪种浮点表示法更好。
有时候,检查错误会造成代价。
比如,如果要求“除以0一定要在运行时报错”,那么运行时就必须增加对于除0的检查(或者更聪明的实现可以让机器抛出硬件异常(x86下,除0是有硬件异常的),然后在消息处理函数里处理这种情况,这样正常情况(不除以0)不会有代价);
如果要求“数组访问越界必须报错”,运行时也要进行数组边界检查(这个目前真的没有用硬件实现的好办法,intel有一些扩展指令、寄存器什么的,试图去用硬件辅助数组越界检查,但目前还没有商业化),也会造成性能代价。
关键是,即使是正确的程序也要为错误检查付出代价。所以,作为系统编程语言,干脆信任程序员,提高正常程序的性能,让错误的程序有“任何想得到或者想不到的行为”。
有时候,不规定一些行为,可以让优化器有更大的优化空间。
比如,如果规定“有符号整数加减越界,是未定义行为”,那么优化器可以放心大胆地假设对于任何有符号整数x,有:x+1>x。因为:如果x+1没有越界,它一定大于x;如果它越界了,既然是“未定义行为”,那么我想怎么做就怎么做。
比如,如果规定“非原子的变量只能由一个线程访问,不能并发访问”,那么优化器可以对程序进行任何变换,只要保证在单线程的前提下是等价的就可以,即使多线程下会出错也没关系,因为已经规定了多线程并发访问是未定义行为。
有时候,某个概念还没有产生,或者不流行,所以标准里根本没有提到,也就是真的(字面上意义的)“未定义”行为。
比如,c11之前C语言的标准根本没提到“线程”。可是1999年,多CPU还是非常非常奢侈的东西。如果你使用多线程,人们会认为你在xxx国家重点实验室工作,你自己搞体系结构,自己搞编译器,自己规定自己的平台上的行为。
【 在 lywzx 的大作中提到: 】
: C/C++里面有一些“未定义行为”,是不是指没有在官方标准(比如C99、C11)里定义的行为?那么官方标准为什么不定义这些行为?
: “未定义行为”又叫依赖机器相关的行为,比如求余操作中余数的符号等等,那么这种操作依赖的是机器的什么部分?是处理器?操作系统?内存?IDE?还是别的什么?
: 谢谢
要说是具体哪个部分,其实是任何部分。你能想到的和想不到的都有。除了你提到的,还有编译器,包括是哪个编译器,哪个版本,以及编译器选项,包括你是否开了调试,用了哪级优化。还有链接了哪个标准库,比如libc++还是libstdc++,还有标准库的哪个版本,比如libstdc++ 2.9还是3.0。
粗略地说,标准如果规定语言的所有细节,要花费多大的时间和精力?一般只是规定接口什么的,很多东西要留给具体实现,即使这样,C/C++标准的制定花了多少年?很多东西也没有研究透彻,比如各种优化措施,这种东西怎么能制定成标准强行让大家遵守呢?
你讲这么多真的好吗?
【 在 nuanyangyang 的大作中提到: 】
: 有时候,世界上,人们对于某个东西没有共识。
: 比如很早以前,机器的一个“字节”(byte)有多少个“比特”(bit),没有共识,有的是8,有的是10,有的是5,或者是别的什么大小,所以c也没有规定
: 就算到了80年代,人们对“IEEE754”浮点数也没有达成共识,富士通的一些计算机有自己的浮点数表示法。
: ...................