多维数组和单维数组之间的转换
这是从我的上一个问题的答案中得出的。
是否可以保证编译器将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)); }
解决方案
回答
我会担心为Matrix [5] [5]之类的东西添加填充以使每一行字对齐,但这可能只是我自己的迷信。
回答
我认为通过多维数组引入填充不会有问题。
数组中的每个元素都必须满足架构所要求的填充要求。数组[N] [M]的内存表示形式总是与[M * N]之一相同。
回答
编译器应将每个数组元素顺序排列在内存中。这两种类型不同的声明是相同的基础内存结构。
回答
从C ++标准开始,引用sizeof
运算符:
When applied to an array, the result is the total number of bytes in the array. This implies that the size of an array of n elements is n times the size of an element.
由此看来," 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 ++标准还指出,数组由连续分配的元素组成,这消除了使用指针和填充进行奇怪操作的可能性。
回答
一个更大的问题是:我们真的需要执行这样的转换吗?
尽管我们也许可以摆脱它,但它还是更具可读性和可维护性,可以完全避免。例如,我们可以始终使用double [m * n]作为实际类型,然后使用包装此类型的类,并可能重载[]运算符以便于使用。在这种情况下,我们可能还需要一个中间类来封装单个行-这样my_matrix [3] [5]之类的代码仍然可以按预期工作。
回答
@康拉德·鲁道夫:
我自己弄混了这两个(行专业/列专业),但是我确实知道这一点:它是明确定义的。
例如,int x [3] [5]是一个大小为3的数组,其元素是大小为5的int数组。(6.5.2.1)从标准中添加有关数组,寻址等的所有规则,我们将得到第二个下标引用连续的整数,而第一个下标引用连续的5个整数对象。 (所以3是更大的数字;我们在x [1] [0]和x [2] [0]之间有5个整数。)