我想在C语言中有一个结构体,它有维度和一个指向矩阵第一个元素的指针,然后用这个指针打印出同一个矩阵的不同元素,但是它不打印任何东西,并且在我试图编译代码时给出一个警告。
代码:
#include <stdio.h>
typedef struct Matrix
{
int height; // matrix height, first dim
int width; // matrix width, second dim
int** firstE; // first matrix elem
} matrix;
int main()
{
int m1[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; //example of two-dimensional array
matrix matrix_1 = {3,3,m1};
printf("%d\n",**(matrix_1.firste)); //should output 1
printf("%d\n",**(matrix_1.firste + 1)); //should output 4
printf("%d\n",*(*(matrix_1.firste)+1)); //should output 2
return 0;
}
警告本身:
.\example.c:14:32: warning: initialization of 'int **' from incompatible pointer type 'int (*)[3]' [-Wincompatible-pointer-types]
14 | matrix matrix_1 = {3,3,m1};
我认为我编写的代码可以工作,因为下面的代码做了我想做的事情。我所期望的是我可以将“m1”作为“int**"赋予上面的结构体。
#include <stdio.h>
int main()
{
int m1[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; //example of two-dimensional array
printf("%d\n",**(m1)); //should output 1
printf("%d\n",**(m1 + 1)); //should output 4
printf("%d\n",*(*(m1)+1)); //should output 2
return 0;
}
3条答案
按热度按时间wsewodh21#
这是一个很常见的误解在C.数组的指针在不是一个二维数组。
在你的例子中,你需要把指向int数组的指针赋给一个指向int的指针数组:
https://godbolt.org/z/vMM5aaqc9
作为旁注:对大小使用
size_t
而不是int
e5nszbig2#
指针和数组有着密切的关系,但它们是完全不同的东西。因此,尽管你可以形成指针数组或数组的数组,但它们也是不同的东西。C 2D数组属于后一种--数组的数组。对应的指针类型是指向数组的指针,而不是指向指针的指针,这正是你的错误信息所告诉你的。
我们可以编写
struct Matrix
,以便您提供的初始化能够正常工作,但如果printf
语句中的访问也能正常工作,则需要struct Matrix
中定义的矩阵具有固定宽度。例如:但是,对于您所考虑的内容,您可能需要一个指向第一行的第一个元素的 single 指针。这将要求您手动执行索引计算:
这显示了每种情况下的完整索引计算,当然您可以简化每种情况。但是在实践中,为了清楚起见并降低出错的风险,我希望您编写一个宏或函数来获取元素:
您也可以指定:
但是,请注意,该宏对指定矩阵的表达式求值两次,如果该表达式有任何副作用,这将是一个问题。我看不出在类似函数的宏中有什么方法可以避免这种情况--您需要使用实际的函数,它将从本质上解决该问题:
在这种情况下,您需要一个单独的函数来存储元素。
第三,您可以将一个(单个)函数和一个宏结合起来,以避免副作用问题,同时也避免了对多个函数的需要:
hujrc8aj3#
问题是
int[3][3]
矩阵的元素是int[3]
数组。因此成员的类型必须是指向此数组的指针。meber类型必须是int(*)[3]
。不幸的是,内部数组的大小是固定的。解决方法是使用指向不完整数组类型int(*)[]
的指针。不完整类型的缺点是它们不能被取消引用。因此,最好通过使用指向VLA的指针来重构原始类型。它编译时没有警告,工作正常。请参阅godbolt。