多维数组的别名
Aliasing of multi-dimensional arrays
众所周知,二维数组是数组的数组,标准要求它是连续分配的非空对象集(6.2.5 类型§20) - 对象在这里是一维数组。
众所周知,对于所有常见实现,以下等式适用于 T arr2d[X][Y]
,其中 T 是类型,X 和 Y 整数常量:
(char *) &arr2d[i][j] == (char *) &arr2d[0][0] + i * Y * sizeof(T) + j * sizeof(T)
以上让我们认为可以允许对一个二维数组和一个相同大小的一维数组,甚至是另一个总大小相同的二维数组进行别名:
例如,以下程序在没有警告的情况下编译和运行,并给出预期的输出:
#include <stdio.h>
int main() {
int i, j, k=0;
int arr2d[3][4]; // array of 3 array of 4 ints
int *arr1 = &arr2d[0][0]; // pointer to first element of an array of 12 ints (1)
int (*arrx)[3] = (int(*)[3]) arr1; //pointer to first row of an array of arrays of 3 ints
//(2)
for (i=0; i<12; i++) arr1[i] = k++; // (3)
for (i=0; i<3; i++) {
for (j=0; j<4; j++) {
printf("%3d", arr2d[i][j]);
}
putc('\n', stdout);
}
for (i=0; i<4; i++) {
for (j=0; j<3; j++) {
printf("%3d", arrx[i][j]);
}
putc('\n', stdout);
}
return 0;
}
但是:
- 行 (1) 和 (3) alias 二维数组 3x4 到一维数组 12
- 第 (2) 行 别名 一个 2D 数组 3x4 到一个 2D 数组 4x3(通过指向 int 的指针)
我的问题是:
- 根据 C 标准,(1) 和 (3) 是否有效?
- 如果是,(2)有效吗?
即使严格的别名规则允许从包含它的对象访问一种类型的对象,标准中有两个元素表明不允许将 2D 数组别名为相同大小的 1D 数组:
兼容类型
6.2.7 Compatible type and composite type
1 Two types have compatible type if their types are the same.
...
3 A composite type can be constructed from two types that are compatible; it is a type that
is compatible with both of the two types and satisfies the following conditions:
- If one type is an array of known constant size, the composite type is an array of that
size; otherwise, if one type is a variable length array, the composite type is that type.
...
These rules apply recursively to the types from which the two types are derived.
一致性:
4 Conformance
...
- ... Undefined behavior is otherwise indicated in this International
Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition
of behavior. There is no difference in emphasis among these three; they all describe
‘‘behavior that is undefined’’.
- A program that is correct in all other aspects, operating on correct data, containing
unspecified behavior shall be a correct program and act in accordance with 5.1.2.3.
...
- A strictly conforming program shall use only those features of the language and library
specified in this International Standard.2) It shall not produce output dependent on any
unspecified, undefined, or implementation-defined behavior, and shall not exceed any
minimum implementation limit.
我的理解是,根据标准,二维数组与一维数组的别名是未指定,因此会导致未定义的行为。使用它的程序仍然是正确的程序,应该可以成功编译,但它的输出是未指定的
严格遵守的程序不应将二维数组别名为一维数组。
也就是说,常见的实现允许它并按预期处理它(每个未定义的行为都是允许的......)为了不破坏严重依赖的遗留代码它。
众所周知,二维数组是数组的数组,标准要求它是连续分配的非空对象集(6.2.5 类型§20) - 对象在这里是一维数组。
众所周知,对于所有常见实现,以下等式适用于 T arr2d[X][Y]
,其中 T 是类型,X 和 Y 整数常量:
(char *) &arr2d[i][j] == (char *) &arr2d[0][0] + i * Y * sizeof(T) + j * sizeof(T)
以上让我们认为可以允许对一个二维数组和一个相同大小的一维数组,甚至是另一个总大小相同的二维数组进行别名:
例如,以下程序在没有警告的情况下编译和运行,并给出预期的输出:
#include <stdio.h>
int main() {
int i, j, k=0;
int arr2d[3][4]; // array of 3 array of 4 ints
int *arr1 = &arr2d[0][0]; // pointer to first element of an array of 12 ints (1)
int (*arrx)[3] = (int(*)[3]) arr1; //pointer to first row of an array of arrays of 3 ints
//(2)
for (i=0; i<12; i++) arr1[i] = k++; // (3)
for (i=0; i<3; i++) {
for (j=0; j<4; j++) {
printf("%3d", arr2d[i][j]);
}
putc('\n', stdout);
}
for (i=0; i<4; i++) {
for (j=0; j<3; j++) {
printf("%3d", arrx[i][j]);
}
putc('\n', stdout);
}
return 0;
}
但是:
- 行 (1) 和 (3) alias 二维数组 3x4 到一维数组 12
- 第 (2) 行 别名 一个 2D 数组 3x4 到一个 2D 数组 4x3(通过指向 int 的指针)
我的问题是:
- 根据 C 标准,(1) 和 (3) 是否有效?
- 如果是,(2)有效吗?
即使严格的别名规则允许从包含它的对象访问一种类型的对象,标准中有两个元素表明不允许将 2D 数组别名为相同大小的 1D 数组:
兼容类型
6.2.7 Compatible type and composite type
1 Two types have compatible type if their types are the same.
...
3 A composite type can be constructed from two types that are compatible; it is a type that is compatible with both of the two types and satisfies the following conditions:
- If one type is an array of known constant size, the composite type is an array of that size; otherwise, if one type is a variable length array, the composite type is that type.
...These rules apply recursively to the types from which the two types are derived.
一致性:
4 Conformance
...
- ... Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior. There is no difference in emphasis among these three; they all describe ‘‘behavior that is undefined’’.
- A program that is correct in all other aspects, operating on correct data, containing unspecified behavior shall be a correct program and act in accordance with 5.1.2.3.
...- A strictly conforming program shall use only those features of the language and library specified in this International Standard.2) It shall not produce output dependent on any unspecified, undefined, or implementation-defined behavior, and shall not exceed any minimum implementation limit.
我的理解是,根据标准,二维数组与一维数组的别名是未指定,因此会导致未定义的行为。使用它的程序仍然是正确的程序,应该可以成功编译,但它的输出是未指定的
严格遵守的程序不应将二维数组别名为一维数组。
也就是说,常见的实现允许它并按预期处理它(每个未定义的行为都是允许的......)为了不破坏严重依赖的遗留代码它。