我需要一个指向静态二维数组的指针。这是怎么做到的?
static uint8_t l_matrix[10][20];
void test(){
uint8_t **matrix_ptr = l_matrix; //wrong idea
}
我遇到各种错误,例如:
- 警告:来自不兼容指针类型的赋值
- 下标值既不是数组也不是指针
- 错误:灵活数组成员的使用无效
最佳答案
这里你想创建一个指向数组第一个元素的指针
uint8_t (*matrix_ptr)[20] = l_matrix;
使用 typedef,这看起来更干净
typedef uint8_t array_of_20_uint8_t[20];
array_of_20_uint8_t *matrix_ptr = l_matrix;
然后你又可以享受生活了:)
matrix_ptr[0][1] = ...;
当心pointer/array world在 C 语言中,对此有很多困惑。
编辑
在此处查看其他一些答案,因为评论字段太短而无法在此处进行。提出了多种替代方案,但没有显示它们的行为方式。这是他们的做法
uint8_t (*matrix_ptr)[][20] = l_matrix;
如果您修复错误并添加地址运算符 &
,如下面的代码片段
uint8_t (*matrix_ptr)[][20] = &l_matrix;
然后,它创建了一个指向 20 uint8_t 类型数组元素的不完整数组类型的指针。因为指针指向数组的数组,所以您必须使用
访问它(*matrix_ptr)[0][1] = ...;
因为它是一个指向不完整数组的指针,所以您不能作为快捷方式来做
matrix_ptr[0][0][1] = ...;
因为索引需要知道元素类型的大小(索引意味着向指针添加一个整数,所以它不适用于不完整的类型)。请注意,这仅适用于 C
,因为 T[]
和 T[N]
是兼容类型。 C++ 没有兼容类型 的概念,因此它会拒绝该代码,因为T[]
和T[10]
是不同的类型。
以下替代方案根本不起作用,因为数组的元素类型,当您将其视为一维数组时,不是 uint8_t
,但是 uint8_t[20]
uint8_t *matrix_ptr = l_matrix; // fail
下面是一个不错的选择
uint8_t (*matrix_ptr)[10][20] = &l_matrix;
你访问它
(*matrix_ptr)[0][1] = ...;
matrix_ptr[0][0][1] = ...; // also possible now
它的好处是可以保留外部维度的大小。所以你可以在上面应用 sizeof
sizeof (*matrix_ptr) == sizeof(uint8_t) * 10 * 20
还有一个答案利用了数组中的项目是连续存储的这一事实
uint8_t *matrix_ptr = l_matrix[0];
现在,形式上只允许您访问二维数组的第一个元素的元素。即以下条件成立
matrix_ptr[0] = ...; // valid
matrix_ptr[19] = ...; // valid
matrix_ptr[20] = ...; // undefined behavior
matrix_ptr[10*20-1] = ...; // undefined behavior
您会注意到它可能工作到 10*20-1
,但是如果您进行别名分析和其他激进的优化,某些编译器可能会做出可能破坏该代码的假设。话虽如此,我从未遇到过失败的编译器(但话又说回来,我没有在实际代码中使用过该技术),甚至 C FAQ 也包含该技术(带有关于其 UB'ness 的警告), 如果你不能改变数组类型,这是最后一个拯救你的选择:)
关于创建指向二维数组的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1052818/