我的目标是有一个结构,它包含一个指向2D无符号字符数组的指针及其宽度和高度,这样我就可以正确地从中检索数据。
#include <stdio.h>
struct wrapper {
unsigned short width;
unsigned short height;
unsigned char ***data;
};
inline unsigned char retrieveValue(struct wrapper *wrapper, unsigned short x, unsigned short y) {
typedef unsigned char (*myCast)[wrapper->height][wrapper->width];
return (unsigned char)((*(myCast)(wrapper->data))[y][x]);
}
unsigned char testWrapperData[2][2] = { {0, 1}, {2, 3} };
struct wrapper wrapper = {
2,
2,
(unsigned char ***)testWrapperData,
};
int main(void) {
printf("%d", retrieveValue(&wrapper, 1, 0));
return 1;
}
这就是我目前使用的,它有效,但我很确定我做错了一些事情(不确定它是否应该只是无符号字符**而不是无符号字符*)。
此外,我想删除myCast的typedef,这样我就可以在一行中拥有所有内容。
三重指针不是必需的,您可以使用unsigned char*
或void*
。但这几乎是无关紧要的,因为您无论如何都不打算使用声明的指针类型。在任何一种情况下,都不涉及多个级别的指针,存储在wrapper->data
中的地址就是2D数组中第一个unsigned char
的地址。2D数组的访问是通过臭名昭著的数组指针衰减进行的纯指针运算。
您可以尝试用几种方法清理代码("尝试"是因为其中一些方法的效果是有争议的)。
-
从
retrieveValue()
中删除对unsigned char
的强制转换,以便编译器可以检查(myCast)
是否使用了正确的类型。 -
使用
testWrapperData
衰变为的类型。这将从铸造中移除外部阵列层,并移除铸造类型的使用。这与您发布的代码完全等效,因为数组的地址与其第一个元素的地址相同,它只是具有不同的类型,从而导致指针衰减的程度增加。inline unsigned char retrieveValue(struct wrapper *wrapper, unsigned short x, unsigned short y) { typedef unsigned char (*myCast)[wrapper->width]; return ((myCast)wrapper->data)[y][x]; } struct wrapper wrapper = { 2, 2, (void*)testWrapperData, };
-
你也可以内联演员阵容,但这实际上是一个品味问题:
inline unsigned char retrieveValue(struct wrapper *wrapper, unsigned short x, unsigned short y) { return ((unsigned char (*)[wrapper->width])wrapper->data)[y][x]; }
-
您可以将转换封装到宏中:
#define getWrapperData(wrapper) ((unsigned char (*)[(wrapper)->width])(wrapper)->data) inline unsigned char retrieveValue(struct wrapper *wrapper, unsigned short x, unsigned short y) { return getWrapperData(wrapper)[y][x]; }
#include <stdio.h>
struct wrapper {
unsigned short width;
unsigned short height;
void *data;
};
inline unsigned char retrieveValue(struct wrapper *wrapper, unsigned short x, unsigned short y) {
typedef unsigned char (*myCast)[wrapper->height][wrapper->width];
return (*(myCast)wrapper->data)[y][x];
}
unsigned char testWrapperData[2][2] = { {0, 1}, {2, 3} };
struct wrapper wrapper = {
2,
2,
&testWrapperData,
};
int main(void) {
printf("%d", retrieveValue(&wrapper, 1, 0));
return 1;
}