这是来自 这是我之前问题的答案。是否保证编译器能够处理 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));
}
有帮助吗?

解决方案

从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++ 标准还规定数组由连续分配的元素组成,这消除了使用指针和填充执行任何奇怪操作的可能性。

其他提示

我认为通过引入 padding 不会有问题 多维的 大批。

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

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

@康拉德鲁道夫:

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

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

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

一个更大的问题是:你真的需要表演这样的演员吗?

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top