内容简介:http://stackoverflow.com/questions/36703033/valid-programs-in-c89-but-not-in-c99
在C99中是否引入或删除了特征/语义,这将使得在C89中编写的定义良好的程序也是
>无效(即根据C99标准不再编译)
>编译,但具有不同的语义.
到目前为止,我的研究结果显然是无效的程序:
> int int(C89§3.5.2)
>隐式函数声明(C89§3.3.2.2)
>不返回从期望返回值的函数(C89§3.6.6.4)
>使用新的关键字作为标识符(例如restrict,inline等)
> hacks涉及//,现在被视为评论.但是,在生产代码中几乎从未遇到过.
微妙的变化,使相同的代码具有不同的语义:
>整数除法已经做了很好的定义,例如-3 / 2现在必须截断为零(C99§6.5.5/ 6),而不是被实现定义(C89§3.3.5/ 6)
> strtod可以通过解析0x或0X来解析C99中的十六进制数
我错过了什么?
在C89出版之前有很多方案被认为是有效的,有些人坚持认为这些方案从未有效. C89包括一个规则,要求只能使用该类型的指针,相关类型或字符类型访问任何类型的对象.在C99发布之前,该规则通常被解释为仅适用于“已命名”对象(静态或自动持续时间的变量,它们通过名称直接访问),并且仅在所涉及的对象没有其地址的情况下在它被用作不同的指针类型之前立即使用.这种解释是由若干因素引起的:
>标准的一个明确目标之一是适应现有的编译器和程序所做的工作,而现有程序对于使用不同类型的指针访问离散命名变量将是罕见的,除非变量的地址为在使用前立即采取指针式打法的很多其他用法颇为普遍.
>标准的基本原理包括作为唯一的例子,该函数接收一个原始类型的指针以编写另一个原始类型的全局变量,使得编译器没有特定的理由期望混叠.能够将全局变量保存在寄存器中显然是一个有用的优化,并且规则的所述目的是在编译器没有理由期望出现混叠的情况下允许这种优化.类似(int *)& foo = 23的非法构造没有什么可以帮助这样的优化,因为代码使用foo的地址和取消引用它的事实应该使任何编译器非常清楚,这并不是故意钝化代码将修改foo.
>有很多种代码需要语义上使用存储器位作为各种类型的能力,标准中没有什么表示规则旨在使 程序员 跳过环(例如通过使用memcpy)来实现本来可能已经被使用的语义特别是考虑到使用memcpy会阻止编译器将整个变量保存在指针访问的寄存器中(从而打破了首先写入规则的目的).
>如果结构类型V和W具有共同的初始序列,则U是包含两者的任何联合类型,p是识别U内的V的V *,则可以使用(W *)(U *)p来访问那些共同的成员,将等同于(W *)p.除非编译器可能显示p不可能是指向包含W的某个联合的成员的指针,否则将需要允许(W *)p访问公共成员;简单地将这种普通成员访问视为合法更有帮助,无论U是否存在,或者U可能存在,而不是搜索借口否认它.
> C89规则中的任何内容都不清楚如何定义分配存储区域的“类型”,或者如何存储一种不再需要的类型的存储可能被重新设计来保存另一种类型的内容.
>跟踪分配给命名变量的寄存器比跟踪分配给其他指针异常的寄存器更容易,而通过指针最小化加载和存储数量感兴趣的代码通常会将事物复制到命名变量并在其上工作.
C99添加了明确适用于分配存储的“有效类型”规则.有些人坚持认为这些仅仅是C89中已经存在的规则的“澄清”,但由于上述原因,我觉得这一观点是站不住脚的.有时候,编译器不将别名规则应用于未命名对象的唯一原因是#5和#6,但反对#1-#4同样重要(并继续适用于C99,就像C89一样).然而,由于C99添加了有效的类型规则,因此许多被C89规则的大多数常见解释视为合法的构造是显然被禁止的.
http://stackoverflow.com/questions/36703033/valid-programs-in-c89-but-not-in-c99
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 程序员编程时戴耳机是在听什么?
- ruby-on-rails – 如何保存ruby builder生成的xml而不是在rails应用程序中呈现它?
- 对象并不一定都是在堆上分配内存的
- 慎用golang中的map,特别是在并发操作中
- 正准备转行或是在自学Java必须具备的几个条件
- 当我们设置 IP 地址为 0.0.0.0 时,是在表达什么
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
RGB转16进制工具
RGB HEX 互转工具
MD5 加密
MD5 加密工具