C语言 通过引用传递2D向量

8nuwlpux  于 2024-01-06  发布在  其他
关注(0)|答案(5)|浏览(96)

我看了很多关于这个主题的回复,但还是没能收到。请理解我正在学习。
有人告诉我,一个向量就是它的第一个元素的地址,所以是一个二维向量。
那么,如果我用指针传递一个2D向量,为什么我会失去使用索引的能力呢?

int vec[10][10] = { 1, 2, 3, 4 };
int *v = vec;

字符串
我为什么不能说

int a = v[1][1]


就像我会做的

int a = vec[1][1]


如果v,指向int的指针,正好指向vec,指向int的指针,它们不都是一样的东西,一样的对象吗?
我读到

int (*v)[N] = vec;


其中N是列数。但这对初学者来说似乎是一件超级棘手的事情。
为什么会这样呢?

编辑

我的大脑对int (*vec)[N]做出了这样的解释,它的意思是 * 指向10int * 的向量的指针。
在一个二维数组中,指向第一个元素的指针是指向N个元素的数组的指针,这是我给自己的解释。
如果int *var = &int的lhs必须从右向左读取,变成“var is a pointer to int“,那么我希望int [N] * var = &2darray从右向左是“var是指向N个int元素的数组的指针”。
但这在语法上对编译器是不正确的,所以我必须使用int (* vec) [N] = 2darray的技巧,从右到左,记住括号优先级变成:
括号在前,从右到左:veca pointer
剩下的,从右到左,就是int [N] .
最后的结果是veca pointeran array of Nint
这有一点道理吗?

mxg2im7a

mxg2im7a1#

编译器应该发出一条消息,

int* v = vec;

字符串
使用不兼容指针类型的指针来初始化类型为int *的指针v
作为初始化器的数组vec被隐式转换为指向其第一个元素的指针。这个二维数组的元素类型是int[10]。因此指向数组元素的指针将具有int ( * )[10]类型。
你不能在你的代码片段中使用像v[1][1]这样的表达式,因为子表达式v[1]的类型是int。也就是说,子表达式v[1]产生的标量对象不是数组。所以这样的表达式v[1][1]是无效的。
如果你愿意写

int vec[10][10] = {1,2,3,4};
int ( *v )[10] = vec;


然后子表达式v[1]产生一个类型为int[10]的对象,它是一个数组。所以你可以对获得的数组应用一个下标运算符,如v[1][1]
如果你有一个一维数组,

int a[n];


然后这个数组的元素具有类型int。并且在表达式中使用的数组有罕见的例外(例如使用in sizeof运算符)被转换为指向类型int *的第一个元素的指针。
另一方面,如果你有一个二维数组,

int a[m][n];


那么数组的元素是类型为int[n]的一维数组,并且指向数组元素的指针具有类型int ( * )[n]

cgvd09ve

cgvd09ve2#

  1. C语言中的数组不是向量。
  2. C中的多维数组是数组的数组
int x[2][3]

字符串
定义两个元素的数组,由3个int元素组成。

  1. C中的数组在用作左值时(即在表达式中)会衰减为指向其第一个元素的指针
  • p.2中的x衰减为指向3个int元素的数组的指针。
  • x[0]' decays to pointer to int`

1.你需要使用指向数组的指针(这没什么特别的)。它是一个具有数组类型的指针。

int (*p)[3];


p定义为指向3个int元素的数组的指针。

slhcrj9b

slhcrj9b3#

很多C语言的设计都是围绕着数组来进行的,当在大多数表达式中使用数组时,数组会衰减为指向第一个元素的指针。[]运算符就是围绕着这样一个假设来设计的--它实际上不能使用数组作为操作数,它总是使用指针。参见Do pointers support "array style indexing"?
传递给[]操作符的指针参数会导致在取消引用的类型上执行指针运算。给定int* ptr;,则ptr[n]会在int类型的项上执行指针运算。
所以对于一个普通数组int vec[10],我们可以写int* ptr = vec;,这很好,因为vec会衰减成指向第一个元素的指针。
int vec[10][10];.int* v = vec;是无效的C。int [10][10]的第一个元素是int [10]。因此,然后vec衰减,它衰减为指向int [10]的指针,此类型与int*不兼容,因此发布得代码违反了赋值约束,编译器必须发出诊断消息。
在我们输入vec[n]的情况下,vec衰减为int(*)[10],因此我们得到int [10]类型的项上的指针算术。
关于数组指针的语法,指向数组int vec[10][10]的指针将被声明为int (*ptr)[10][10]。当我们已经有了指针而不是数组时,就没有衰减这回事了,所以ptr[n]实际上会给予我们类型为int [10][10]nth 数组项......这是没有帮助的。我们没有一个int [10][10]项的数组。要真正得到一个int [10]项,这更可能是我们想要的,我们首先必须取消对指针的引用:(*ptr)[n]。语法相当繁琐。
因此,最简单的方法是将指针声明为一维短指针:int (*ptr)[10]。这直接对应于一个数组int vec[n][10]。我们可以使用ptr[i][j]来访问二维数组中的int项。或者,我们可以使用vec[i][j],在这种情况下,vec会衰减,并且我们也会在二维数组中获得一个int

mm5n2pyu

mm5n2pyu4#

我为什么不能说

int a = v[1][1]

字符串
因为v是指向int的指针,你只能访问一个元素,使用一个访问[]操作符,而不是两个。如果你正确地声明了它,那么你就可以做到:

int (*v)[10] = vec;


那么你可以正确地使用v[1][1]甚至v[9][9],因为现在v是一个指向10个整数的10个数组的指针。
这里的问题是,当你只说vec时,C语言将其解释为 * 指向第一个元素的指针 *(具有指向访问数据的指针类型)这也是一个数组,所以它(再次)衰减为指向第一个元素的指针,这是指向int的指针。
甚至,你可以使用一个指向完整内容的指针:

int (*v)[10][10] = &vec;


但是,你必须使用2D数组的地址。这也是有效的。

注意:

括号是必要的,因为v必须是指向数组的指针,而不是指针数组(如果您没有使用它们,它应该是)

xoshrz7s

xoshrz7s5#

正如其他答案中所指出的,int *v = vec;是一个类型不匹配,应该生成一个诊断。编译时使用高级警告并使这些警告出错是一个很好的做法,可以尝试避免导致未定义行为或其他bug的错误。
使用gcc -Wall -Wextra -Werror或对clang使用相同的标志。
正如你的问题所述,正确的定义是:

int (*v)[10] = vec;

字符串
要破译这些定义,您应该学习并使用spiral rule

相关问题