我试图理解C99第6.5.6节(加法运算符)的第8和第9段
第8段是否意味着:
int a [4];
int *p = a;
p --; /* undefined behaviour */
p = a + 4; /* okay */
p --; /* okay */
p += 2; /* undefined behaviour */
p = a;
p += 5 - 5; /* okay */
p = p + 5 - 5; /* undefined behaviour */
对于第9段,我的理解是ptrdiff_t总是足够大以容纳2个指针的差异。但措辞如下: '如果值适合ptrdiff_t类型的对象'似乎表明这种理解是错误的。我的理解是错误的还是C99意味着别的东西。
您可以在此处找到标准草案的链接: http://cboard.cprogramming.com/c-programming/84349-c-draft-standards.html
答案 0 :(得分:2)
我不认为你的解释是正确的。在我的版本(n1256)第9段中指出:
如果结果在该类型的对象中无法表示,则 行为未定义
就是这样。如果差异大于PRTDIFF_MAX
或小于PTRDIFF_MIN
,则行为未定义。
请注意,这会给程序员带来负担,以检查差异是否适合ptrdiff_t
。一个“懒惰”的平台实现可以为ptrdiff_t
选择一个窄类型,让你处理它。
检查这不是直截了当的,因为你不能在没有激怒UB的情况下进行减法。您必须使用两个指针指向同一对象内部(或刚好超出)的信息以及该周围对象的边界。
答案 1 :(得分:0)
我同意您对第8段的理解。标准说
如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。
似乎C假设数组内没有指针溢出,因此您可以在保留在数组内时递增/递减指针。如果结果指针离开数组,则可能发生溢出并且行为未定义。
关于第9段,我想该标准考虑到你可能会有一个架构,它给你32位指针和32位数据类型,但由于两个32位指针的差异实际上是一个符号加上32位(所以33位),并非每个指针差异都可能匹配到32位ptrdiff_t。使用2补充架构这不是问题,但它可能是其他架构上的问题。