C中是否允许使用负数组索引?

bod*_*ydo 104 c arrays

我只是读了一些代码,发现这个人arr[-2]用来访问之前的第二个元素arr,如下所示:

|a|b|c|d|e|f|g|
       ^------------ arr[0]
         ^---------- arr[1]
   ^---------------- arr[-2]
Run Code Online (Sandbox Code Playgroud)

这是允许的吗?

我知道那arr[x]是一样的*(arr + x).所以arr[-2]就是*(arr - 2),这似乎确定.你怎么看?

Mat*_*hen 162

那是正确的.从C99§6.5.2.1/ 2:

下标运算符[]的定义是E1 [E2]与(*((E1)+(E2)))相同.

没有魔力.它是1-1等价的.与取消引用指针(*)时一样,您需要确保它指向有效的地址.

  • 在旧书中,`[]`被引用为指针算术的*语法糖*.*最喜欢的混淆初学者的方法是写'1 [arr]` - 而不是'arr [1]` - 并观察他们猜测这意味着什么. (29认同)
  • 当你的32位int索引是负数时,64位系统(LP64)会发生什么?是否应该在地址计算之前将索引提升为64位signed int? (4认同)
  • @Paul,来自§6.5.6/ 8(附加运算符),"当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型.如果指针操作数指向一个元素对于一个数组对象,并且该数组足够大,结果指向一个元素偏离原始元素,使得结果元素和原始数组元素的下标之差等于整数表达式." 所以我认为它会被提升,`((E1)+(E2))`将是一个具有预期值的(64位)指针. (4认同)
  • 还要注意,您不必取消引用指针即可获取UB。仅计算“ somearray-2”是不确定的,除非结果在“ somearray”开始到结束为止的1范围内。 (2认同)

Jam*_*lis 62

仅当arr指针指向数组中的第二个元素或更高的元素时,这才有效.否则,它无效,因为您将访问数组边界之外的内存.所以,例如,这是错误的:

int arr[10];

int x = arr[-2]; // invalid; out of range
Run Code Online (Sandbox Code Playgroud)

但这没关系:

int arr[10];
int* p = &arr[2];

int x = p[-2]; // valid:  accesses arr[0]
Run Code Online (Sandbox Code Playgroud)

然而,使用负下标是不寻常的.

  • @Matt:第一个例子中的代码产生了未定义的行为. (13认同)
  • 它无效.根据C标准,它明确地具有未定义的行为.另一方面,如果`int arr [10];`是其前面有其他元素的结构的一部分,`arr [-2]`可能是明确定义的,你可以确定它是否基于`offsetof `等 (4认同)
  • 对不起,死灵法术,但我只是喜欢 K&R 对“非法”的含义的含糊不清。最后一句话听起来好像越界访问会引发编译错误。那本书对初学者来说是毒药。 (4认同)
  • @Martin 公平地说,这本书是在我们行业历史的早期写的,当时期望“非法”被解释为“不要这样做,你不被允许”而不是“你将被阻止这样做”。 (4认同)
  • 在K&R第5.3节中找到它,接近结尾:`如果确定元素存在,也可以在数组中向后索引; p [-1],p [-2]等在语法上是合法的,并且指的是紧接在p [0]之前的元素.当然,引用不在数组范围内的对象是违法的.但是,你的例子更好地帮助我理解它.谢谢! (3认同)

Mat*_*ner 10

听起来不错.然而,你会合法地需要它,这是一种罕见的情况.

  • 它不是*罕见 - 它在例如邻居运营商的图像处理中非常有用. (7认同)

Igo*_*aka 7

可能是arr指向数组的中间位置,因此arr[-2]指向原始数组中的某些内容而不会超出范围.


Pau*_*l R 7

我不确定这是多么可靠,但我只是阅读以下关于64位系统上负数组索引的警告(大概是LP64):http://www.devx.com/tips/Tip/41349

作者似乎在说,具有64位寻址的32位int数组索引可能导致错误的地址计算,除非数组索引被显式提升为64位(例如通过ptrdiff_t强制转换).我实际上已经看到了他的性质的错误与PowerPC版本的gcc 4.1.0,但我不知道它是否是编译器错误(即应该按照C99标准工作)或正确的行为(即索引需要转换为64比特的正确行为)?

  • 这听起来像编译器错误. (3认同)