文章目录
在本系列第一篇博客中讲到变量的本质是一段存储空间的别名,那么是不是必须通过这个别名才能使用这段存储空间呢?
我们先看一个问题?下面的程序输出什么,为什么?
我们来实际编译运行一下:
#include<stdio.h>
int main()
{
int i = 5;
int* p = &i;
printf("%d, %p\n", i, p);
*p = 10;
printf("%d, %p\n", i, p);
return 0;
}
$ gcc 26-1.c -o 26-1
$ ./26-1
5, 0x7ffd47f77a8c
10, 0x7ffd47f77a8c
可以看到我们并没有改变变量 i 的值,而是通过指针 p 修改它所指向的内存空间(就是变量 i),也就是修改了变量 i 的值。因为指针 p 指向变量 i
1 *号的意义
- 在指针声明时,* 号表示所声明的变量为指针
- 在指针使用时,* 号表示取指针所指向的内存空间中的值
可以这样理解,内存就是一间房子,变量就是房子里面放的东西,指针就是门牌号。定义指针就是拿到了一个门牌号,指针 p 指向变量 i,就是将这个门牌号装在了存放变量 i 的房子上,当然可以取下来装在别的房子上,也就是指针 p 指向了另一个变量。* 号就是一把钥匙,通过这个钥匙就可以拿到房子里面的东西,这就是 *p 解引用。
指针 p 保存着变量 i 的内存地址,可以这么理解
- p 等价于 &i
- *p 等价于 i
下面看一个指针使用示例:
// 26-1.c
#include<stdio.h>
int main()
{
int i = 0;
int* pI;
char* pC;
float* pF;
pI = &i;
*pI = 10;
printf("%p, %p, %d\n", pI, &i, i);
printf("%ld, %ld, %p\n", sizeof(int*), sizeof(pI), &pI);
printf("%ld, %ld, %p\n", sizeof(char*), sizeof(pC), &pC);
printf("%ld, %ld, %p\n", sizeof(float*), sizeof(pF), &pF);
return 0;
}
编译运行结果如下:
$ gcc 26-1.c -o 26-1
$ ./26-1
0x7ffca1ad8f8c, 0x7ffca1ad8f8c, 10
8, 8, 0x7ffca1ad8f90
8, 8, 0x7ffca1ad8f98
8, 8, 0x7ffca1ad8fa0
- 上面的程序,指针 pI 的值和变量 i 的地址是一样的,pI 和 &i 等价,* 号是钥匙,*pI 拿到了房间的钥匙,并更换的房间的东西,由 0 变成 10
- 可以看到不管定义什么类型的指针,指针大小是一样的,也很好理解,不管房子是多大的,里面放的什么东西,门牌号长度都不会变,不能因为你住的是豪宅就换个贼长的门牌号吧
- 32位系统指针长度为 4 字节,64 位系统指针长度为 8
2 传值调用与传址调用
- 指针是变量,因此可以声明指针参数
- 当一个函数体内部需要改变实参的值,则需要使用指针参数
- 函数调用时实参将复制到形参
- 指针适用于复杂数据类型作为参数的函数中
下面看一个指针使用的示例,:利用指针交换变量
// 26-2.c
#include<stdio.h>
void SWAP(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
int main()
{
int a = 1;
int b = 2;
printf("a = %d, b = %d\n", a, b);
SWAP(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
注意,千万不能写成如下代码:
void SWAP(int a, int b)
{
int t = a;
a = b;
b = t;
}
这样是达不到交换目的的,采用值传递时,形参是实参的拷贝,改变形参的值不影响实参的变化。因为形参有自己独立的存储空间,作为函数内部的局部变量,在函数调用结束后就被释放,因此不影响实参的值。 所以 SWAP(int a, int b) 函数中 a, b 的交换不会影响到 main() 函数中。
3 常量与指针
通过几个例子来学习 const 修饰指针的情形
上面的内容不用死记,只需要看清楚 const 修饰的是谁就可以了。如果 const 修饰 *p,则 *p 不可变;如果 const 修饰 p,则 p 不可变;如果两个都修饰,都不可变
下面就来实际操作一个,看下面代码中,哪些行会报错
// 26-3.c
#include<stdio.h>
int main()
{
int i = 0;
const int *p1 = &i;
int const *p2 = &i;
int* const p3 = &i;
const int* const p4 = &i;
*p1 = 1;
p1 = NULL;
*p2 = 1;
p2 = NULL;
*p3 = 1;
p3 = NULL;
*p4 = 1;
p4 = NULL;
return 0
}
根据前面的知识,我知道,*p1, *p2, p3, *p4, p4 被 const 修饰,是不可修改的,下面就编译一下,看看我们的分析是否正确。
编译结果在第 10,13,17,19,20 行报错,和我们的分析结果完全一样
4 小结
1、指针是 C 语言中一种特别的变量
2、指针所保存的值是变量的地址
3、可以通过指针修改内存中得任意地址内容