Lea*_*ros 17 c c99 c89 language-lawyer
是否在C99中引入或删除了特征/语义,这些特性/语义也可以用C89编写一个定义良好的程序
到目前为止我的调查结果,涉及明显无效的程序:
restrict,inline等)//,现在被视为评论.但是,在生产代码中几乎从未遇到过.微妙的变化,使相同的代码具有不同的语义:
strtod通过解析0x或获得了在C99中解析十六进制数的能力0X我错过了什么?
在 C99 发布之前,有很多程序在 C89 下被认为是有效的,但有些人坚持认为它们永远无效。C89 包括一条规则,要求任何类型的对象只能使用该类型、相关类型或字符类型的指针来访问。在 C99 发布之前,此规则通常被解释为仅适用于“命名”对象(通过名称直接访问的静态或自动持续时间的变量),并且仅适用于相关对象没有其地址的情况在它被用作不同的指针类型之前立即获取。这种解释是出于以下几个因素:
该标准的既定目标之一是适应现有编译器和程序正在执行的操作,尽管现有程序很少使用不同类型的指针访问离散命名变量,除非采用变量地址的情况在这种使用之前,指针类型双关语的许多其他用法非常常见。
该标准的基本原理包括作为其唯一示例的函数,该函数接收一种基元类型的指针以写入另一种基元类型的全局变量,使得编译器没有特殊理由期望出现别名。能够将全局变量保留在寄存器中显然是一种有用的优化,并且该规则的既定目的是在编译器没有理由预期会发生别名的情况下允许进行此类优化。禁止像 like 这样的构造对(int*)&foo=23;此类优化没有任何帮助,因为代码获取 的foo地址并取消引用它的事实应该使任何没有故意迟钝的编译器清楚地知道代码将要修改foo。
有很多种代码在语义上需要能够将内存位用作各种类型,并且标准中没有任何内容表明这些规则旨在让程序员跳过障碍(例如通过使用 memcpy)来实现本来可以轻松实现的语义在没有规则的情况下获得,特别是考虑到使用 memcpy 会阻止编译器在指针访问期间将全局变量保留在寄存器中(从而违背了最初编写规则的目的)。
如果结构类型V和W具有共同的初始序列,U是包含两者的任何联合类型,并且p是V*标识 aV内的 a U,(W*)(U*)p则可用于访问这些共同成员,并且将等效于(W*)p。除非编译器可以表明p不可能是指向包含 的某个联合的成员的指针W,否则需要允许(W*)p访问公共成员;简单地将这种共同成员访问视为合法,无论是否存在或在何处U存在,都比寻找借口拒绝它更有帮助。
C89 规则中没有任何内容明确说明如何定义已分配存储区域的“类型”,或者如何将保存不再需要的一种类型的内容的存储重新用于保存另一种类型的内容。
跟踪分配给命名变量的寄存器比跟踪分配给其他指针异常的寄存器更容易,并且对通过指针最小化加载和存储数量感兴趣的代码通常会将内容复制到命名变量并在那里对其进行处理。
C99 添加了明确适用于分配存储的“有效类型”规则。有些人坚持认为这些只是对C89中已经存在的规则的“澄清”,但基于上述原因,我认为这种观点站不住脚。流行的说法是,编译器不对未命名对象应用别名规则的唯一原因是 #5 和 #6,但反对意见 #1-#4 同样重要(并且继续适用于 C99,就像适用于 C89 一样)。尽管如此,由于 C99 添加了有效类型规则,许多被 C89 规则的最常见解释视为合法的构造被明确禁止。
| 归档时间: |
|
| 查看次数: |
619 次 |
| 最近记录: |