指针带来的一些符号的理解
- 我们写的代码是给编译器看的,代码要想达到你想象的结果,就必要编译器对你的代码的理解和你自己对代码的理解一样。编译器理解代码就是理解的符号,所以我们要正确理解C语言中的符号,才能像编译器一样思考程序、理解代码。
星号*
- (1)C语言中*可以表示乘号,也可以表示指针符号。这两个用法是毫无关联的,只是恰好用了同一个符号而已。
- (2)星号在用于指针相关功能的时候有2种用法:
- 第一种是指针定义时,*结合前面的类型用于表明要定义的指针的类型;
- 第二种功能是指针解引用,解引用时*p表示p指向的变量本身
int *p1; // *和int结果,表明p的类型是int *,也就是
// p是指向int类型变量的指针
int* p2;
int*p3;
int * p4;
- 实际编译测试,p1到p4都没有警告,说明4种写法编译器认为是一样的,都是定义了 int *类型的指针p
// 把*和指针变量放在一起,而不是和int挨着,是为了一行定义多个变量时好理解
int *p5, *p6; // 这样才是定义了2个int *指针变量p5、p6
int *p5, p6; // p5是int *指针,p6是int的普通变量
int* p5, p6; // p5是int *指针,p6是int的普通变量
int a = 23;
int b = 0;
// 演示指针变量解引用
int *p; // *p就是我们说的星号的第一种用法
p = &a;
b = *p; // b = 23 // *p就是我们说的星号的第二种用法
printf("b = %d.\n", b);
取地址符&
- 取地址符使用时直接加在一个变量的前面,然后取地址符和变量加起来构成一个新的符号,这个符号表示这个变量的地址。
int a; // &a就表示a的地址。
int *p;
p = &a;
- 编译器一看到&a,就知道我们是要把变量a的地址赋值给指针变量p,因为变量a的地址是编译器分配的,所以只有编译器才知道a的地址。所以我们没法直接把a的地址的数字赋值给p,只有用符号&a来替代。
- 理解&a,*p这样的符号,关键在于要明白当&和*和后面的变量结合起来后,就共同构成了一个新的符号,这个新的符号具有一定的意义。
指针定义并初始化、与指针定义然后赋值的区别
- (1)指针定义时可以初始化,指针的初始化其实就是给指针变量初值(跟普通变量的初始化没有任何本质区别)。
- (2)指针变量定义同时初始化的格式是:int a = 32; int *p = &a;
- (3)不初始化时指针变量先定义再赋值:int a = 32; int *p; p = &a; 正确的 *p = &a; 错误
左值与右值
- (1)放在赋值运算符左边的就叫左值,右边的就叫右值。所以赋值操作其实就是:左值 = 右值;
- (2)左值与右值意义:
- 当一个变量做左值时,编译器认为这个变量符号的真实含义是这个变量所对应的那个内存空间;
- 当一个变量做右值时,编译器认为这个变量符号的真实含义是这个变量的值,也就是这个变量所对应的内存空间中存储的那个数。
- (3)左值与右值的区别,就好象现实生活中“家”这个字的含义。譬如“我回家了”,这里面的家指的是你家的房子(类似于左值);但是说“家比事业重要”,这时候的家指的是家人(家人就是住在家所对应的那个房子里面的人,类似于右值)
int a = 3, b = 5;
a = b; // 当a做左值时,我们关心的是a所对应的内存空间,而不是其中存储的3
b = a; // 当a做右值时,我们关心的是a所对应空间中存储的数,也就是5