我试图从3D数组中获取2D子数组,并将其传递给函数。原因是要像操作2D数组的数组一样操作这个3D数组中的数据。然而,数据应该像传递二维数组一样传递给函数。
pixelval_t subFrameData[MAX_SUBFRAMES][ARRAY_WIDTH][ARRAY_HEIGHT];
我使用了一些指针魔法,它工作了,并且不显示警告。然而,在一个边缘情况下,它确实给出了一个[-Wstringop-overflow=]警告。
那么下面是有效的:
// function prototype
void SendImageBuffer_Subframe(pixelval_t dataarr[ARRAY_WIDTH][ARRAY_HEIGHT]);
...
// Some function somewhere
...
for (int i = 0; i < MAX_SUBFRAMES; i++) {
pixelval_t * ptr = &(subFrameData[i][0][0]); //get pointer of first element of 2D array
SendImageBuffer_Subframe((pixelval_t (*)[ARRAY_HEIGHT]) ptr); //cast pointer and call function
}
...
但是,如果我对固定索引而不是变量执行相同的操作:
// function prototype
void SendImageBuffer_Subframe(pixelval_t dataarr[ARRAY_WIDTH][ARRAY_HEIGHT]);
...
// Some function somewhere
...
pixelval_t * ptr = &(subFrameData[0][0][0]); //get pointer
SendImageBuffer_Subframe((pixelval_t (*)[ARRAY_HEIGHT]) ptr); //cast pointer and call function
}
...
给出如下警告:
main.c: In function ‘main’:
main.c:67:9: warning: ‘SendImageBuffer_Subframe’ accessing 48 bytes in a region of size 12 [-Wstringop-overflow=]
67 | SendImageBuffer_Subframe((pixelval_t (*)[ARRAY_HEIGHT]) ptr);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.c:67:9: note: referencing argument 1 of type ‘pixelval_t (*)[6]’ {aka ‘short int (*)[6]’}
main.c:35:6: note: in a call to function ‘SendImageBuffer_Subframe’
35 | void SendImageBuffer_Subframe(pixelval_t dataarr[ARRAY_WIDTH][ARRAY_HEIGHT]){
| ^~~~~~~~~~~~~~~~~~~~~~~~
但是,代码确实可以工作,并且它给出了预期的输出。
在编写这些代码时,我发现下面的代码可以正常工作,没有错误
const int defaultIndex = 0;
pixelval_t * ptr = &(subFrameData[defaultIndex][0][0]);
SendImageBuffer_Subframe((pixelval_t (*)[ARRAY_HEIGHT]) ptr);
我猜结果是一样的。这只是一个编译器的怪癖,还是有一个适当的解释?还是我在重铸指针的过程中完全走错了方向?
注意:我知道我可以通过直接操作数组指针来避免所有这些问题。但是我发现数组的语法糖很好地保持了代码的可理解性。
或者我只是完全在错误的轨道上重铸指针?
是的。
原因是将3D数组中的数据当作2D数组的数组来操作。
其中是一个二维数组。这就是C语言中多维数组的工作原理。my_3D_array[i]
给出一个二维数组。不需要强制转换。
所以你的函数应该是:
for (int i = 0; i < MAX_SUBFRAMES; i++) {
SendImageBuffer_Subframe(subFrameData[i]);
}
至于为什么(pixelval_t (*)[ARRAY_HEIGHT])
强制转换工作,这只是因为碰巧在该内存位置上有一个1D数组。和一个二维数组。还有一个3D阵列。还有一个单品。它们都从同一个地址开始
任何带有数组的C函数都会将数组静默地调整为指向该数组第一个元素的指针。在pixelval_t dataarr[ARRAY_WIDTH][ARRAY_HEIGHT]
的情况下,第一个项目的类型是pixelval_t [ARRAY_HEIGHT]
,指针指向pixelval_t (*) [ARRAY_HEIGHT]
。因此,强制转换不会导致任何编译器消息,因为:
void SendImageBuffer_Subframe(pixelval_t dataarr[ARRAY_WIDTH][ARRAY_HEIGHT]);
100%等价于:
void SendImageBuffer_Subframe(pixelval_t (*dataarr)[ARRAY_HEIGHT]);