多维数组的别名

众所周知,2D数组是一个数组数组,标准要求它是一个连续分配的非空对象集 (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  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)将2Darrays3x4 别名为1Darrays12
  • line(2)将2D数组3×4 别名为2D数组4×3(通过指向int的指针)

我的问题是:

  • (1)和(3)是否符合C标准?
  • 如果是,(2)有效吗?

即使严格的别名规则允许从包含它的对象访问一种类型的对象,标准中有两个元素可以说不允许将2D数组别名化为相同大小的1D数组:

兼容型

6.2.7兼容型和复合型

1如果类型相同,则两种类型具有兼容类型。

3复合型可以由两种兼容的类型构成; 它是一种兼容两种类型并满足以下条件的类型:

  • 如果一个类型是已知常量大小的数组,则复合类型是该大小的数组 ; 否则,如果一个类型是可变长度数组,则复合类型是该类型。

这些规则递归地应用于从中派生两种类型的类型

一致性:

4一致性

  1. ……未定义的行为在本国际标准中以“未定义的行为”或任何明确的行为定义省略来表示 。 这三者之间的重点没有区别; 他们都描述”未定义的行为”
  2. 在所有其他方面正确的程序,对正确的数据进行操作,包含未指定的行为,应该是正确的程序,并按照5.1.2.3行事。
  3. 严格符合的程序应仅使用本国际标准中规定的语言和库的那些特征.2) 它不应产生依赖于任何未指定,未定义或实现定义的行为的输出 ,并且不得超过任何最小实现限制。

我的理解是,标准没有指定具有1Darrays的2Darrays的混叠,因此导致未定义的行为。 使用它的程序仍然是一个正确的程序 ,应该成功编译,但其输出是未指定的

严格符合的程序不应将2D数组别名为1D数组。

话虽这么说,常见的实现允许它按预期处理它(每个未定义的行为允许…),以便不破坏严重依赖它的遗留代码。