对于一个数组,如 int a[4]; 如果只是给出数组名a,编译器不知道该取该数组的第几个元素,因此编译器不会自动取值,而是返回该数组的首地址(第一个元素的地址)。其实,数组名a就是数组本身,并不是数组的首地址,只是当只是给出了数组名a的时候,而又同时需要取值时,数组名a才会被隐式转换为该数组的首地址。因此,int *p=&a;和int *p=a的效果是一样的,只是前者是显示的,而后者是隐式的。
例如,数组名a在以下情况就不是数组的首地址的:1.sizeof(a) 得到的结果为16,即a是一个数据类型,长度为4的int数组类型,是数组本身,没有进行隐式转换;2.&a 表示数组的首地址,并不是指针的指针,而是指向长度为4的int数组的指针,一个常量指针,其指针类型为: in (*)[4],此处4不能省略,因为"指向不确定长度的指针" 是没有意义的,编译器若不知道该指针指向的类型,就无法编译指针的加减法运算(指针指向类型的长度未知,加减法的位移量就未知)。int (*p)[4]=&a; 定义一个指针p,并初始化为数组a的地址,等价于:int *p=a; 3. C++中取引用时a也不是指针。
char* test2()
{
char p[] = "hello world";
return p;
} //错误代码
char* test2()
{
char *p = "hello world";
return p;
}
对于以上代码,char p[ ] = "hello world";与char *p = "hello world";是有着本质区别的,前者首先定义了一个数组p,且用后面的字符串初始化该数组p,数组p的作用域为该函数内部,数组生存期和作用域与声明方式相关。而且该数组没有 const 资格符,字符串内容是可以修改的。这个数组首地址不能在函数中返回(因为函数结束的同时,p已经被销毁了),除非声明用了 static 。对于后者,声明一个指针。字符串字面量本身成为一个静态存储期的数组,它再隐式转换成指针以初始化声明的指针。这个字符串是不可修改的(修改会导致未定义行为,数组本身可放在只读内存区)。它的首地址可以在函数中返回。
对于函数名,其原理与上面基本相同。函数名其实并不是函数的入口地址,只是被隐式转换了。函数名只是函数本身。