指针也就是内存地址,指针变量是用来存放内存地址的变量。指针没有实际的值,在使用变量的时候不要错以为指针等于变量。指针是门牌号,房间是变量,房间里的东西是变量的值。
房间有户型,三室一厅、二室一厅等。不管房间是什么类型的,门牌号都是唯一的。只要有门牌号我就能无误地找到这个房间。
G、7776 都是存储在内存中的值,变量名对应着它们。而每一个变量都有唯一的内存地址(机器地址)。指针指向的就是内存地址,而不是实际的值。
通过间接运算符*
声明一个指针变量,指针变量的数据类型要与指向的变量的数据类型保持一致。假如,feet 变量是一个int
类型,指针的类型也是int
。指针通过&
得到变量的内存地址,把内存地址取出来给 pfeet 指针变量:
int main(void) { int feet = 10; int* pfeet = &feet; printf("before updating feet is %d\n", feet); // before updating feet is 10 *pfeet += 10; printf("now feet is %d\n", feet); // now feet is 20 return 0; }
上面说到,指针不等于变量,第四行,pfeet 只是得到了内存地址,直接修改 pfeet 相当于把内存地址修改了,但实际上不影响 feet 在内存中的实际内存地址。第七行,在引用指针变量时要在前面加上间接运算符*
,意思是找到内存地址所对应的变量,修改变量的值。
指针与变量的作用好像都是一样,指针也没有什么特别之处?实际上,变量的局限性很大,指针的自由度很高。得益于作用域,函数内声明的局部变量不可以被其他函数直接访问和修改。
void change(int, int); int main(void) { int x = 10, y = 5; change(x, y); printf("[3] x = %d, y = %d\n", x, y); return 0; } void change(int x, int y) { printf("[1] x = %d, y = %d\n", x, y); x = 20; y = 10; printf("[2] x = %d, y = %d\n", x, y); }
在 main 函数中声明了 x 和 y,再把这两个变量传递给 change 函数修改。修改 x 和 y 之后是否影响 main 函数中的 x 和 y?
很显然不行,实际上 main 函数中声明的 x 和 y 的内存地址与 change 函数中的 x 和 y 内存地址不是一致的。也就是说,两个函数中同样的变量名,实际上不是一个东西。
如果非要改变 main 函数的 x 和 y,可以使用指针,指针不受函数作用域的影响。指针指向的是内存地址,只要拿到内存地址,找到门牌号,就能修改、更新变量的值。
下面通过指针来修改 main 函数的 x 和 y:
void change(int*, int*); int main(void) { int x = 10, y = 5; change(&x, &y); printf("[3] x = %d, y = %d. x Address = %p, y Address = %p\n", x, y, &x, &y); return 0; } void change(int* x, int* y) { printf("[1] x = %d, y = %d. x Address = %p, y Address = %p\n", *x, *y, x, y); *x = 20; *y = 10; printf("[2] x = %d, y = %d. x Address = %p, y Address = %p\n", *x, *y, x, y); }
change 函数接收的不是一个变量了,而是一个指针。函数找到内存地址所对应的变量,修改变量的值。那么,main 函数的 x 和 y 也随着改变: