我需要一个指向静态二维数组的指针.这是怎么做到的?
static uint8_t l_matrix[10][20];
void test(){
uint8_t **matrix_ptr = l_matrix; //wrong idea
}
我收到各种错误,如:
- 警告:来自不兼容指针类型的赋值
- 下标值既不是数组也不是指针
- 错误:灵活数组成员的使用无效
我需要一个指向静态二维数组的指针.这是怎么做到的?
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] = ...;
当心C中的pointer/array world,围绕这一点有很多困惑.
在这里查看一些其他答案,因为注释字段太短,不能在那里做.人们提出了多种替代方案,但没有展示它们的行为方式.他们是这样做的
uint8_t (*matrix_ptr)[][20] = l_matrix;
如果修复错误并添加运算符&
的地址,如以下代码段所示
uint8_t (*matrix_ptr)[][20] = &l_matrix;
然后创建一个指向不完整数组类型的指针,数组类型为20 uint8_t.因为指针指向数组,所以必须使用
(*matrix_ptr)[0][1] = ...;
因为它是指向不完整数组的指针,所以您可以将cannot作为快捷方式
matrix_ptr[0][0][1] = ...;
因为索引需要知道元素类型的大小(索引意味着在指针上加一个整数,所以不适用于不完整的类型).请注意,这只适用于C
,因为T[]
和T[N]
是兼容类型.C++没有compatible types的概念,所以它会拒绝该代码,因为T[]
和T[10]
是不同类型.
以下替代方案根本不起作用,因为当您将数组视为一维数组时,它的元素类型是not uint8_t
,而不是uint8_t[20]
uint8_t *matrix_ptr = l_matrix; // fail
以下是一个很好的 Select
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
次,但如果您使用别名分析和其他激进的优化,一些编译器可能会做出一个可能会 destruct 代码的假设.话虽如此,我从来没有遇到过一个编译器在它上面失败(但话说回来,我没有在实际代码中使用这种技术),甚至C FAQ也包含了这种技术(带有关于其UB’ness的警告),如果您无法更改数组类型,这是最后一个保存您的选项:)