一维数组名可以赋值给一个普通的指针

数组通常转换成指向首元素的指针。

int a[4];
int *ap = a;

二维数组名却不可以赋值给一个指向指针的指针

二维数组转换成的指针也指向首元素(一维数组),而不指向指针。

int b[2][4];
int (*bp)[4] = b;

据 @emmm 的评论编辑了回答。


在C语言中,数组在多数表达式中(例外包括取址和sizeof),隐式转换为指向其首元素的指针右值,称为数组退化。

二维数组的元素是一维数组,因此其退化后的类型是指向一维数组的指针,而不是指向指针的指针。


我觉得能提出这个问题的人,对指针是真正地思考过的。这个问题的答案也很简单,就一句话「不同类型的东西不能互相赋值」。举个例子:

家猫、野猫和狮子都是猫科动物,家猫和野猫可以繁衍出后代,而家猫和狮子是没法繁衍出后代的。你看,同属于猫科动物的它们不一定都能繁衍后代。

回到这个问题上,我们以int a[]举例,a是数组名,它本质上是int *类型的指针,而普通的指针p如果也是int *类型的话,那么a就可以赋值给p,也就是a是家猫,p是野猫,都是同一个子科目,它们可以繁衍后代。

二维数组int b[][]的数组名b,本质上是int (*)[]类型的指针,指针的指针int **q的类型是int **,俩不同类型的东西不可以互相赋值2793068398这里如果b是家猫的话,q就是狮子,是俩不同的子科目,不可以繁衍后代。

所以,它们看著都是指针,但是指针的类型也分好几种呢,就是这么简单咯!

正版!朱伟恋词2022考研英语辞汇单词书历年真题5500词淘宝¥ 39.80去购买?


可以,不过有编译」警告罢了。警告是在提示你可能存在潜在问题,而不是不能这样做,你完全可以强制转换。编译器行为罢了,就像char* s = "hello";其实字元串常量应该是const char*,但是C编译器偏偏没有警告,C++编译器就会有警告,因为C++的类型检查比C严格。


至于为什么有警告:

抛个问题给题主,int a[5]; 请问a的类型是什么?

明白了,也就知道了。


经过大佬 @左江 提醒,不同类型的指针做类型强转还是会被编译器搞鬼的,被称为「严格别名规则」,读书少确实不太行。这规则确实会给编译器优化提供一定的操作空间,但是确实容易限制程序猿的发挥(′;︵;`)。有兴趣的盆友可以去看看gcc官方文档:https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gcc.pdf搜索-fstrict-aliasing关键字了解详情,或者看看c99标准里的对应关键字也行。

建议题主不要听那些说指针跟数组是一回事的人瞎BB,类型什么的,都是浮云。指针是根针,数组是个池子,能有啥关系?

只是恰好,多维数组是数组的数组,数组指针的偏移量粒度等于该数组类型的长度而已

数组跟指针,是毫不相干的俩东西,只是某些情况下看起来比较像。

数组名是个特殊的指针常量,数组跟指针没关系。其实作为解引用符号时,方括弧下标和星号都是专属于指针的,跟数组没关系,之所以可以用来表示对数组元素的索引,只是对数组名这个特殊的指针常量的解引用而已。数组是个池子,指针是根针,能有关系才见鬼。

另,附上c里一加一可以等于很多数的表达式

c里,一个数等于多少,取决于俩东西:

1.实际存储介质中存储的内容,

2.读取它的方式(即认为该地址上存储的类型是啥)

即说到底指针有且仅有俩属性:值和类型

数组有且仅有俩属性:数组长度和数组维数

本来俩毫不相干的东西,只是有些时候看起来有点像,但是不要被表象迷惑,毕竟只是看起来而已。


没怎么用过。不过「指向指针的指针」那是二级指针啊。和你二维数组有什么关系。c语言的二维数组实际上在内存模型上就是所谓的「一维」连续数组。就是个普通指针而已。


推荐阅读:
相关文章