array和pointer

虽然声明的数组名表面上可以像指针一样使用,但是两者还是有很大的区别的

数组和指针:

当正常声明一个数组的时候,会发现编译器为这个数组分配的空间正好是数组元素占用的空间,不会为数组名分配有额外的空间

如果声明一个N维数组,你会发现所有维的第一个元素都指向分配的第一个内存地址

如果尝试对数组名进行取地址操作,那么你仍将得到分配的第一个内存地址。但是这个地址中存放的值其实是数组的第一个元素,而不是数组名代表的一个地址类型的值。所以并不会有一个内存地址(开发者可见的,当然编译器会为自己记录一下符号表之类的值)中存放着数组名,也就是数组名只是被编译器维护在符号表中的,而不存在一个实际的变量。编译器在维护的时候将它的地址和它的值都设置为分配的第一个内存地址。

所以,显然的,数组名不能被当作左值,任何将数组名当作左值的操作都会使编译器发出非左值的error

但是如果是一个指针,无论是通过将现有的数组赋给它还是动态申请内存来为它赋值,它本身都有一个实实在在的内存空间用于维护自身,所以它可以作为左值

函数传数组:

编译器在编译的时候会为参数和返回值申请栈空间

所以实际上是有实在的空间存储参数的

在向函数传递数组参数的时候,会向变量中实际传递这个数组名代表的值,因而这个参数占有实际的存储空间,这就成为一个指针了,所以这里的“数组名”将可以作为左值

这也是合理的,函数维护这个变量到底是一个数组还是一个指针将会花费额外的精力,在为参数申请栈空间的时候也要分情况考虑,如果使用一个指针,这将简单的多

但是编译器只会进行一重这样的退化,当参数是多维数组时,函数实际得到的是指向维数少一的数组的指针

这个指针的类型就是数组元素类型的指针,但是在获取它的大小的时候会有一个warring:
warning: 'sizeof' on array function parameter 'a' will return size of 'const double *' [-Wsizeof-array-argument]

到底还是一个指针

动态分配的数组就不会具有这样的性质,因为它们毕竟还是指针,每一重都会多占用一部分内存地址用于存放指针,但是数组就不会

猜你喜欢

转载自blog.csdn.net/qq_40711741/article/details/82776033