Dennis Ritchie关于C(1988)的别名分析

2021-03-20 23:36:02

1998年1998年由Dennis Ritchie从Comp.Lang.c中的说明非常流行,因为诺纳里亚的概念绝对悄然回到了标准。我已经逐字再现了它,但轻微地格式化了可读性。对于进一步阅读,请尝试Linus Torvalds(Pre-Well)注释,John Reger关于别名的论文以及C 2X标准的这一提议。

下面转载的是我作为官方评论发送的漫长的文章,对x3j11发送。它有两部分;第一个指出了当前定义的一些问题,“第二个是关于”诺纳里亚斯的诽谤“。”通过介绍,关于“const”的重要事项是当前的措辞,在第3.3.4节中说,指向要素限定对象的指针可以投射到指向普通对象的指针,而是“如果尝试通过转换的指针修改指向对象,则该行为是未定义的。”由于函数原型倾向于将指针转换为规定的指针,因此出现困难。在与各种X3J11成员的讨论中,我了解到本节现在被视为无故障错误,并且没有人认为它将持续到其当前形式。尽管如此,似乎最聪明的是以原来的强大形式留下评论。委员会的意图是无关紧要的;只有他们的文件很重要。

文章的第二部分是关于诺纳里亚斯这样的。似乎也有可能甚至对这个主题委员会的意图困惑。

这是为什么我不喜欢X3J11类型限定符的文章。这是我自己的意见;我不是在& t。

让我首先说,我不相信即使是12月前的资格赛(`const'和`挥发性')携带其体重;我怀疑他们增加了学习成本和使用语言的成本不会以更大的表达偿还。 “挥发性”特别是用于深度应用的散热器,并通过其他方式表达更好。它的主要美德是几乎每个人都可以忘记它。 `const'同时更有用,更令人窒息;由于其在库界面中存在,您无法避免了解它。尽管如此,我不争辩于限定符的剥离,如果只是因为为时已晚。

基本问题是,不可能使用C的X3J11定义来编写真实程序。委员会创造了一种不可能或实际使用的虚幻语言。虽然“const”的问题可能欠粗心起草规范,但是“诺纳里亚斯”是一个完全误解的概念,不得生存。

可以返回其第一个参数。必须使用“const noalias”声明此第一个参数;否则,它将是非法的(通过分配的约束,3.3.16.1)传递const或noalias对象的地址。也就是说,原型中的类型限定符不仅仅是界面的可选智慧;如果是将某些类型的数据传递给此或大多数其他库例程,则需要它们。

不幸的是,由于返回的语义(3.6.6.4)和演员(3.3.4),X3J11的语言无法以X3J11的语言返回它所承诺的价值。 const和noalias限定符是通过在strchr中投射的剥离,或通过其返回语句隐式地完成,Strchr返回一个指针(因为`const')无法存储,并且(因为`noalias')无法存储被解除引人入胜;通过规则,它是无用的。 (顺便提及,我认为这一观察是汤米梅在几年前制作的;它令人不安地留下了不一致的遗体。)

虽然标准的普通词语拒绝它,涂抹适当的“非常数”在表达式上沉默,沉默编译器有时是安全的,因为最可能的“const”对象的实现将允许它们通过任何访问路径读取它们,并将诊断尝试通过在运行时生成访问违规故障来更改它们。也就是说,在常见的实现中,添加或获取指针的“const”限定符不能在规则`中创建未隐含的任何错误`,不会通过任何访问路径修改正版const对象。

然而,我必须强调这不是X3J11所写的规则,而其图书馆与其语言不一致。使用X3J11 / 88-001编写翻译的人在自由于(确实,建议)随身携带的每个指针,(在3.3.4之后)当指向Const-Pervicized对象时保持关闭被铸成普通指针。例如,此实现将防止STRCHR的许多真实用途。我在想类似的东西

相关观察是字符串文字不属于Const Char的类型。“的确,理由(88-004版)说,”但是,字符串文字没有[这种类型],以避免问题指针类型检查,特别是库函数......'如果此秃头语句应该被视为X3J11的规则是搭配的备注以外的任何东西?委员会介绍了“Const”的限定符,并且还使字符串销售,但无法连接这两个概念。

“诺纳里亚斯”更危险;委员会正在种植时间爆炸,肯定会在人们的面部爆炸。将普通指针分配到指向“诺纳里亚斯”对象的指针是编译者承担委员会规则完全合法的攻击优化的许可,而是使哈希明显安全。同样,该问题在图书馆中最可见;参数声明为“Noalias类型*”尤其问题。

为了使用新的参数声明编写此类库例程,实际上是违反3.3.4的实践:“将指向诺纳丽亚级的类型...”可以转换为......非纳义统治类型。如果指向对象通过转换的指针引用,则该行为是未定义的。“因此,”const“发生的问题现在更糟糕了; Strchr没有有趣和合法的用途。

如何代码原型指定诺纳亚州指针的例程?如果您无法违反3.3.4,但是尝试重写临时变量的声明,以使其在类型中同意参数,这变得难以确保例程工作。考虑Strtok的规范:

它保留了一个静态指针,以其可写的,“诺纳里亚斯”的第一个参数。您可以确定此例程可以在规则下安全吗?我已经研究过它,答案是有条件的,所以提供标准的某些部分作为福音(例如,“诺纳里亚斯”句柄在某些时间不在某些时间时不会同步)。这是一个非常狡猾的事情。对于其他例程,确定需要完整的重写:例如,QSORT充满了指针,该指针将参数阵列传播并在此处更改它。如果这些本地指针与“诺亚斯”有资格,则它们可能都指向阵列部分的不同虚拟副本;在任何情况下,参数本身都可能具有可能通过尝试对其进行排序的虚拟对象。

“诺纳里亚斯”规则向后有分配和压铸限制。将普通指针分配给规则指针(PC = P)由规则很好地定义,并且是安全的,因为它限制了您可以使用PC执行的操作。禁止(P = PC)周围的另一种方式,推测,它是因为它创建了不可写入对象的可写访问路径。对于“诺亚丽莎”,“规则是相同的(PNA = P是OK,禁止PNA),但逼真的安全要求完全不同。这两个分配同样可疑,因为这两个都会为对象创建两个访问路径,其中一个表现为虚拟。

这是观察不对称的另一种方法:参数列表中的“const类型*”存在是一块有用的接口信息,但是最令人愉快的“Noalias类型*”不是。鉴于宣言

什么信息可以从中收集?有些委员会成员显然认为它传达给读者或编译器,即常规是安全的,条件是字符串不重叠。他们被误解了。也许委员会的意图没有反映在目前的标准的话语中,但我可以在那里找到任何证明他们的信仰。规则(第65行,第19-20行)指定了这些[noalias] lvalues可访问的所有对象,这是两个数组参数的整体。

我可以在魔术功能的要求中得出任何东西吗?我可以在有什么东西可以得出关于它承诺的事情或不做的事情吗?我从理由中学到的只是这样的例程禁止我让争论重叠,但这与标准的差异,这带来了更强的禁令。

在功能本身内,事情同样差。 a` const键入*'参数,尽管它为Strchr和其他例程提供了问题,但有用地限制功能:它不允许通过指针存储。但是,在具有`noalias类型*'参数的函数中,除了bizarre限制之外,没有任何内容:它不能将参数投入普通指针,并且它不能将参数分配给另一个诺纳州指针而不创建不需要的句柄潜在的虚拟对象。界面必须说诺纳里亚斯,或者以任何速度都表明诺纳里亚斯,所以例程的作者都有3.5.3(手柄,虚拟物体)的所有怪诞的发明,如此。 “诺纳里亚斯”的完全错误是它旨在传达的信息根本不是对象的属性。 “常备”为所有技术故障,至少是对象的真正财产; “诺纳里亚斯”不是,委员会困惑的尝试通过固定对象上的新限定符来改善优化的困惑破坏了语言。 “诺纳里亚斯”是一个不必要的伪造发明,而不是任何情况都足够了。

早期的语言与旨在帮助优化的Gizmos调情,并且通常会抛弃它们。例如,原始的Fortran有一个没有帮助太多,困惑的人的频率陈述,并且被删除了。 PL / 1具有“正常/异常”和“使用/设置”属性,遭受类似的命运。今天,这些通常被视为青少年实验。

另一方面,CRAY的Fortran编译器建议了“诺纳里亚斯”的不足,其中有20个单独的关键字,可以控制优化的各种细节。该等同于#Pragma等效,因此,尽管他们在尝试理解程序的含义时,可以忽略它们。也许有一些原因来提供用于在特定代码的特定代码中断言机制,编译器可以自由地对可能发生的锯齿的种类进行乐观假设。我不知道改变语言规范的任何可接受的方式,以表达这种优化的可能性,我不知道可能会产生多少性能改善。我会鼓励编译器编写者通过#Pragma或其他方式进行扩展,看看他们可以提出哪些想法和改进,但我确信任何类似诺纳里亚斯提案的情况都应该是标准。

K& R C具有一个重要的内部矛盾(禁止禁止打印函数的变量函数)和规则与现实之间的一个重要分歧(常见的与ref / def外部数据定义)。这些矛盾在整个年内对我来说是一种尴尬,解决它们在X3J11的议程上很高。 X3J11确实设法提出了足够的,如果尴尬,解决了第一个问题。他们的解决方案与我的第二个相同(制定规则,然后发出毯子许可证违反它)。

我知道“符合”和“严格符合”程序之间存在区别。虽然X3J11的限定符规则不一致,因此大多数名义上的X3J11编译器将忽略,或者只有警告,X3J11所说的,X3J11所说的,人们会以某种方式幸存下来。毕竟,C有浪费差异和外部问题。

尽管如此,我强烈建议坚定地了解语言规范,没有人可以在有用的编译器中体现。这个建议是基于痛苦的体验。

不得重新重写,重新格式化或重新发明。草案的描述缺陷,但这不是问题。从开始完成这个概念是错误的。它否定了每个勇敢的承诺x3j11,曾经做过编纂现有实践,保留现有的代码组,并保持(敢于我说呢?)“C”的精神。“

const有两个优点:将事物放在只读内存中,并表达界面限制。例如,说

是一种合理的方式,表明例程无法更改其第一个参数所引用的对象。我认为措辞的微小变化保留了美德,但消除了当前方案中的矛盾。

1)重写Page 47,3.3.4(铸造运算符)的第3-5行,以删除修改指向对象的未定义,或者完全删除这些行(因为未明确讨论不合格的投射不合格。 )

2)重写第54行,第14-15行的约束,可以在不考虑限定符的情况下分配指针。

3)保留所有目前的限制,反对修改不可修改的百次值,即表现为合格类型的类型。

5)将约束(或讨论或示例)添加到分配,以清除分配给实际类型为Const-Pervicied的对象的非法性,无论使用哪种访问路径都可。有一个清单约束,易于检查(左侧不是规定的),而且也是一个非检职约束(左侧不是秘密规格)。效果应该是转换指向规定的和普通物体的指针是合法的,定义的;避免通过指针赋予最终来自“const”对象的指针是程序员的责任。

这些规则放弃了一定数量的检查,但它们节省了语言的一致性。