Wil*_*son 10 c pointers language-lawyer
考虑以下情况:
美国国家半导体的SC/MP有一些指针,当你继续递增它们时,它将从0x0FFF滚动到0x0000,因为增量电路不会传播进位超过较高字节的较低的nybble.因此,例如,如果我想要while(*ptr++)遍历以null结尾的字符串,那么我可能最终ptr指向数组外部.
在PDP-10上,由于机器字长于地址1,指针可能在包含地址的字的上半部分中具有标签和其他数据.在这种情况下,如果递增指针导致溢出,则其他数据可能会被更改.对于非常早期的Macintoshes,在ROM为32位清洁之前也是如此.
所以我的问题是关于C标准是否说明指针递增的含义.据我所知,C标准假定它应该以与递增整数相同的方式逐位工作.但是,正如我们所看到的那样,这并不总是成立.
符合标准的C编译器是否可以发出一个简单的adda a0, 12来递增指针,而不检查进位传播的存在或不存在会导致奇怪?
1:在PDP-10上,地址是18位宽,但机器字是36位宽.机器字可以包含两个指针(对于Lisp很方便)或一个指针,加上位域,这意味着"添加另一个间接级别",段,偏移等.或者机器字当然可以不包含指针,但这不是与这个问题有关.
2:将一个添加到地址.这是68000汇编程序.
Eri*_*hil 14
只要结果指向有效对象或仅通过有效对象,指针算术的行为仅由C标准指定.更重要的是,标准没有说明指针的位是什么样的; 实施可以安排它们以适合自己的目的.
所以,不,该标准没有说明当指针递增到地址翻转时会发生什么.
如果while你引用的循环只进行一个元素超过数组的结尾,它在C中是安全的.(按照标准,如果ptr已经增加到数组末尾之外的一个元素,并x指向数组中的任何元素,包括第一个,然后x < ptr必须是真的.所以,如果ptr已经在内部滚动,C实现负责确保比较仍然有效.)
如果while循环可能会ptr超出数组末尾的多个元素,则C标准不会定义行为.
人们经常会问,"为什么C还有未定义的行为,无论如何?".这是其中一个重要原因的一个很好的例子.
让我们坚持使用NS SC/MP示例.如果硬件规定递增指针值0x0FFF不能正常工作,我们有两个选择:
将代码翻译p++成等效的if(p == 0x0FFF) p = 0x1000; else p++;.
翻译p++直增量,但钻机的事情了,这样没有正确分配的对象永远重叠的地址涉及0x0FFF,例如,如果有人曾经写道,最终操纵指针值代码0x0FFF并添加一个到它,并得到一个奇怪的答案,就可以说"那是不确定的,所以任何事情都可能发生".
如果采用方法#1,生成的代码会变得越来越大.如果采用方法#2,生成的代码最有效.如果有人抱怨这种奇怪的行为,那么问问为什么编译器不能发出做"更合理"的代码,你可以简单地说,"我们的任务是尽可能高效."