3

这是从我的上一个问题的这个答案中得出的。编译器是否保证将其视为array[4][4]相同array[16]

例如,以下任一调用api_func()是否安全?

void api_func(const double matrix[4][4]);

// ...

{
  typedef double Matrix[4][4];

  double* array1 = new double[16];
  double array2[16];

  // ...

  api_func(reinterpret_cast<Matrix&>(array1));
  api_func(reinterpret_cast<Matrix&>(array2));
}
4

6 回答 6

3

来自 C++ 标准,指的是sizeof运算符:

当应用于数组时,结果是数组中的总字节数。这意味着元素数组的n大小n是元素大小的倍数。

由此,我会这么说,double[4][4]并且double[16]必须具有相同的基础表示。

即,给定

sizeof(double[4]) = 4*sizeof(double)

sizeof(double[4][4]) = 4*sizeof(double[4])

那么我们有

sizeof(double[4][4]) = 4*4*sizeof(double) = 16*sizeof(double) = sizeof(double[16])

我认为符合标准的编译器必须同样实现这些,而且我认为这不是编译器会意外破坏的东西。实现多维数组的标准方法按预期工作。打破标准需要额外的工作,可能没有任何好处。

C++ 标准还规定数组由连续分配的元素组成,这消除了使用指针和填充做任何奇怪的事情的可能性。

于 2008-09-11T01:42:11.113 回答
2

我认为多维数组引入的填充没有问题。

数组中的每个元素都必须满足架构强加的填充要求。数组 [N][M] 在内存中的表示形式总是与 [M*N] 之一相同。

于 2008-09-11T00:53:49.513 回答
1

每个数组元素应由编译器按顺序排列在内存中。这两个声明虽然不同的类型是相同的底层内存结构。

于 2008-09-11T00:53:53.180 回答
1

@康拉德鲁道夫:

我自己把这两个(行专业/列专业)搞混了,但我知道这一点:它定义明确。

例如,int x[3][5] 是一个大小为 3 的数组,其元素是大小为 5 的 int 数组。(§6.5.2.1)添加标准中关于数组、寻址等的所有规则。你得到第二个下标引用连续的整数,而第一个下标将引用连续的 5-int 对象。(所以 3 是更大的数字;在x[1] [0] 和x[2] [0] 之间有 5 个整数。)

于 2008-09-11T23:43:24.430 回答
0

我会担心为 Matrix[5][5] 之类的东西添加填充以使每一行单词对齐,但这可能只是我自己的迷信。

于 2008-09-11T00:12:30.003 回答
0

一个更大的问题是:你真的需要进行这样的演员阵容吗?

尽管您可能能够摆脱它,但完全避免它仍然更具可读性和可维护性。例如,您可以始终使用 double[m*n] 作为实际类型,然后使用包装此类型的类,并可能重载 [] 运算符以方便使用。在这种情况下,您可能还需要一个中间类来封装单行——这样 my_matrix[3][5] 之类的代码仍然可以按预期工作。

于 2008-09-11T07:24:35.517 回答