-2

我知道负长度数组具有未定义的行为,但是 E1[E2] 的标准与 (*((E1)+(E2))) 相同,我希望有些东西可以工作。

所以在这种情况下,我要做的是创建一个跨度方向为 -32 的数组,因此我期望获得的可访问索引是 -31 到 0。

我使用的是 0 到 255 的 8 位无符号字符和 -128 到 +127 的有符号字符,但这也适用于 32 位整数和 64 位整数。

我使用 C99 声明可变长度数组的能力来构造负跨越数组,特别是我正在编译到 GNU99 C 标准。

我将这些值分配给索引并随时打印出来,一切似乎都很好。

当我在数组索引 [-31] 处创建一个指向值的指针,然后在 0 到 31 之间循环,打印这些值时,这很奇怪。

const signed char length = 32;
const signed char negativeLength = -length;

signed char array[negativeLength];
for ( signed char ii = 0; ii > negativeLength; ii-- ) {
    array[ii] = ii;
    printf( "array %d\n", array[ii] ); /* Prints out expected values */
}

printf( "==========\n" );

signed char * const pointer = &array[negativeLength + 1];
for ( unsigned char ii = 0; ii < length; ii++ ) {
    printf( "pointer %d\n", pointer[ii] ); /* Begins printing expected values then goes funky */
}

我每次都得到不同的结果,但是对于 32 来说,前 3 个值通常开始正常,然后它变得很时髦,开始打印出 -93 到 +47,然后在索引指针 [8]、数组 [-23] 它又好了。

我在 iPad 2 上运行它。

这里到底发生了什么?当 iPad 检测到负跨越数组长度时,它是否会弄乱指针或数组?

4

2 回答 2

0

我有时主张在 C 标准未定义行为的情况下理解在某些 C 实现中观察到的行为,因为它可以说明某些实现如何工作或计算机如何工作。但是,在这种情况下:不要那样做。

要访问具有任意整数索引的数组,从 X(包括)到 Y(不包括),请执行以下操作:

ElementType ArrayMemory[Y-X], *Array = ArrayMemory - X;

如果 X <= 0 <= Y 且 X < Y,则其行为由 C 标准定义。

于 2013-06-10T12:20:36.437 回答
0

当你做了一些未定义的行为时,为什么你会期望某些东西起作用?

虽然E1[E2]等同于*(E1 + E2)定义明确,但您访问的数据定义不明确,因此所有赌注都没有。

于 2013-06-10T11:01:50.440 回答