左值和右值
以前一直以为数组就是指针,但是直到我发现下面这两句的输出一样的时候,我才发现我错了
#include <stdio.h>
int main(){
int a[2];
printf("%#X\n",a);
printf("%#X\n",&a);
}
数组作为右值的时候,会被当成一个指针,因为总不可能把整个数组的元素全部输出来,但是被&取地址的时候是作为左值,就被当成一个对象,所以&返回的就是第一个元素的地址。
具体可以参考这篇博客
https://blog.csdn.net/imred/article/details/45441457
拓展:结构和对象
但是struct和c++的class/对象,作为右值的时候不会被当成指针,比如下面这个代码
#include <stdio.h>
int main(){
int a[5];
printf("%#X\n",a);
printf("%#X\n",&a);
struct S{
int e;
char t;
};
struct S s;
struct S s2;
struct S s3;
printf("%#X\n",&s);
printf("%#X\n",s);
printf("&e:%#X\n",&(s.e));
printf("%#X\n",&s2);
printf("%#X\n",s2);
printf("%#X\n",&s3);
printf("%#X\n",s3);
printf("e: %x\n",s.e);
printf("e: %x\n",s2.e);
printf("e: %x\n",s3.e);
printf("t: %d\n",s.t);
printf("t: %d\n",s2.t);
printf("t: %d\n",s3.t);
}
输出是这样的
0X62FE00
0X62FE00
0X62FDF0
0X1
&e:0X62FDF0
0X62FDE0
0XFFFFFFFF
0X62FDD0
0XCE1350
e: 1
e: ffffffff
e: ce1350
t: 0
t: -1
t: 0
输出struct的时候输出的是第一个int的值,而不是它的地址,因为没有初始化,所以输出是随机的。
指针与数组
所以说指针和数组还是有区别的,如下面这个例子
/*bugging.c*/
#include <stdio.h>
#include <stdlib.h>
static char buff [256];
static char* string;
int main ()
{
printf ("Please input a string: ");
gets (string);
printf ("\nYour string is: %s\n", string);
}
会出现"Segment Fault"错误
用数组声明会给buff分配栈里面的空间,虽然没有初始化值,但是是合法的地址,但是只声明一个指针只会给这个指针变量分配一个地址,它的值没有初始化,默认为0,是不合法的地址,应该再加一句
string=buff;
buff作为右值时可以当成一个指针,所以赋值给string是没有问题的。
另外,数组变量作为左值是不能修改的,只能修改对应位置上的值,也就是说数组的名字包含的是一个常量指针const pointer,而不是一个普通的指针变量,它在符号表里面就对应这个数组对象了,不能再赋其他的对象给它。也就是说
int val[3] = { 5, 10, 20 };
val[0] = 1;//ok
val = {2,3,4};// Array type 'int[3]' is not assignable
第二句可以,第三局不可以,无法通过编译。参考https://www.geeksforgeeks.org/cpp-pointers/?ref=shm的Array Name as Pointers部分。