我只是读了一些代码,发现这个人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等价的.与取消引用指针(*)时一样,您需要确保它指向有效的地址.
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)
然而,使用负下标是不寻常的.
我不确定这是多么可靠,但我只是阅读以下关于64位系统上负数组索引的警告(大概是LP64):http://www.devx.com/tips/Tip/41349
作者似乎在说,具有64位寻址的32位int数组索引可能导致错误的地址计算,除非数组索引被显式提升为64位(例如通过ptrdiff_t强制转换).我实际上已经看到了他的性质的错误与PowerPC版本的gcc 4.1.0,但我不知道它是否是编译器错误(即应该按照C99标准工作)或正确的行为(即索引需要转换为64比特的正确行为)?