对多维数组的一维访问:它是明确定义的行为吗?

对多维数组的一维访问:它是明确定义的行为吗?

我想我们都同意,通过以一维方式解引用(可能是偏移的)指向其第一个元素的指针来访问真正的多维数组被认为是惯用的C,例如:


void clearBottomRightElement(int *array, int M, int N)

{

    array[M*N-1] = 0;  // Pretend the array is one-dimensional

}



int mtx[5][3];

...

clearBottomRightElement(&mtx[0][0], 5, 3);

然而,我的语言律师需要说服这实际上是明确定义的C!特别是:


是否标准保证编译器不会把填充例如,在中间mtx[0][2]和mtx[1][0]?


通常,索引关闭数组的末尾(除了结尾之外)是未定义的(C99,6.5.6 / 8)。所以以下内容显然是未定义的:


struct {

    int row[3];           // The object in question is an int[3]

    int other[10];

} foo;

int *p = &foo.row[7];     // ERROR: A crude attempt to get &foo.other[4];

因此,根据相同的规则,人们会期望以下内容未定义:


int mtx[5][3];

int (*row)[3] = &mtx[0];  // The object in question is still an int[3]

int *p = &(*row)[7];      // Why is this any better?

那为什么要定义呢?


int mtx[5][3];

int *p = &(&mtx[0][0])[7];

那么C标准的哪一部分明确允许这个?(为了讨论,我们假设是c99。)

请注意,我毫不怀疑这在所有编译器中都能正常工作。我要查询的是标准是否明确允许这样做。


郎朗坤
浏览 493回答 3
3回答

沧海一幻觉

您想要进行访问的唯一障碍是类型对象int [5][3]并且int [15]不允许彼此别名。因此,如果编译器意识到类型的指针指向前者的int *一个int [3]数组,则它可能会施加数组边界限制,从而阻止访问该int [3]数组之外的任何内容。您可以通过将所有内容放在包含int [5][3]数组和int [15]数组的联合内部来解决此问题,但是我真的不清楚联合黑客是否会将人们用于类型惩罚实际上是明确定义的。这种情况可能稍微有点问题,因为你不会打字单个单元格,只有数组逻辑,但我仍然不确定。应该注意的一个特殊情况是:如果您的类型是unsigned char(或任何char类型),那么将多维数组作为一维数组访问将是非常明确的。这是因为unsigned char与标准重叠的一维数组被标准明确定义为对象的“表示”,并且本质上允许对其进行别名。
打开App,查看更多内容
随时随地看视频慕课网APP