不知道大家有没有像我一样百度/谷歌过:对数组名取地址究竟是否合法。
浏览了一圈下来 基本上就两种解释:未定义行为 表示整个数组。
那么 ,究竟哪个是对的呢?
首先先来解释一下什么是未定义行为:对于某种代码操作或者数据的修改造成的结果取决于编译器或者不同环境的行为,就是未定义行为。
最典型的例子: i++ + ++i ;甚至是对char型取负值(ps:char型在C语言里并不是像int一样是默认有符号的,有的编译器解释的char是signed char 有的则是 unsigned char)都属于未定义行为。
那么什么是表示整个数组呢?
这边举一个例子:
如果有一个指针p指向整个数组arr,那么p+1的操作刚好指向数组arr最后一个元素的下一个地址
如:一个数组int arr[3],arr[0]的地址假设为0x00(十进制0)。根据arr[0]的地址我们能推出arr[1]的地址是0x04(十进制4),arr[2]是0x08*(十进制8)。此时一个指针p指向整个数组 那么p+1的值就是0x0c(十进制12)。说白了,指针p的定义形式就是int (*p)[3]。如果条件成立的话(&arr)+1也应该是0x0c。
回到正题:对数组名取地址是未定义行为吗?
这里是《C++ Primer Plus》的解释:
从这里我们能看到对数组名取地址确实是有意义的,就是表示整个数组。
我们可以自己亲自验证一下:首先是在windows操作系统下的VS2017编译器:
测试用的声明:int arr[3][4]
完全通过!0个error 0个warning!
我们再换个环境:Ubuntu18下的gcc vi:
这次结果就非常明显了。对数组取地址后+1的值和p+1的值一致!
另外这里提一下:对于这个arr数组而言arr、arr[0] 、&arr的值是完全相同的,但是意义却完全不同!
arr表示的是:arr[0]的地址,所以arr+1即为arr[1]的地址;
arr[0]表示的是:arr[0][0]的地址,所以arr[0]+1即为arr[0][1]的地址;
&arr则就是本篇的主角了,表示:整个数组arr的地址,即:&arr+1的值和&arr[2][4]的值相等(虽然越界,但是这么说很形象)。