C中是否允许负数组索引?
我只是读了一些代码,发现这个人正在使用arr[-2]
访问arr
之前的第二个元素,如下所示:
|a|b|c|d|e|f|g| ^------------ arr[0] ^---------- arr[1] ^---------------- arr[-2]
这是允许的吗?
我知道arr[x]
和*(arr + x)
。 所以arr[-2]
是*(arr - 2)
,这似乎没问题。 你怎么看?
那是对的。 从C99§6.5.2.1/ 2开始:
下标算子[]的定义是E1 [E2]与(*((E1)+(E2)))相同。
没有魔法。 这是一个1-1的等价。 像往常一样,在取消引用指针(*)时,您需要确保指向一个有效的地址。
这只有在arr
是指向数组中第二个元素的指针时才有效。 否则,它是无效的,因为你将访问数组的边界之外的内存。 所以,例如,这将是错误的:
int arr[10]; int x = arr[-2]; // invalid; out of range
但是这样可以:
int arr[10]; int* p = &arr[2]; int x = p[-2]; // valid: accesses arr[0]
然而,使用否定下标是不寻常的。
听起来对我很好。 然而,如果你合法地需要这种情况,那将是一个罕见的情况。
可能是那个arr
指向了数组的中间,因此arr[-2]
指向原始数组中的某些东西而没有超出范围。
我不确定这是多么可靠,但我只是阅读以下关于64位系统(LP64大概是负数组索引)的警告: http : //www.devx.com/tips/Tip/41349
作者似乎是说,64位寻址的32位int数组索引可能会导致地址计算错误,除非将数组索引明确提升为64位(例如,通过ptrdiff_t转换)。 我实际上已经看到了PowerPC版本的gcc 4.1.0的性质的错误,但我不知道它是一个编译器错误(即应该按照C99标准工作)或正确的行为(即索引需要转换为64位正确的行为)?
我知道这个问题已经回答了,但我无法拒绝分享这个解释。
我记得编译器devise的原理,我们假设一个是int数组,int的大小是2,a的基地址是1000。
a[5]
如何工作 – >
Base Address of your Array a + (index of array *size of(data type for array a)) Base Address of your Array a + (5*size of(data type for array a)) ie 1000 + (5*2) = 1010
这个解释也是为什么数组中的负指数在C中工作的原因
即如果我访问a[-5]
它会给我
Base Address of your Array a + (index of array *size of(data type for array a)) Base Address of your Array a + (-5 * size of(data type for array a)) ie 1000 + (-5*2) = 990
它将返回位置990处的对象。通过这个逻辑,我们可以访问C中的数组中的负索引。
关于为什么有人想要使用负面的索引,我已经在两种情况下使用它们:
-
有一个组合数字表,告诉你梳[1] [ – 1] = 0; 您可以在访问表之前始终检查索引,但这样代码看起来更干净并且执行速度更快。
-
把一个centinel放在一个桌子的开始。 例如,你想使用类似的东西
while (x < a[i]) i--;
但是,你也应该检查i
是积极的。
解决scheme:使a[-1]
为-DBLE_MAX
,以使x<a[-1]
始终为假。