指针

指针是什么?

数据在内存中的地址也称为指针,而存放指针(地址)的变量为指针变量。

指针变量的值就是某份数据的地址

1
2
3
4
5
6
7
8
9
int main()
{
int a = 10; //在内存中开辟一块空间,用来存放10
int *p = &a; //使用&(取地址符),获得a的地址,将获得的地址放在指针变量p中。

return 0;
}
//a占空间四个字节,指针变量p存放哪个字节的地址呢?
//答案是存放第一个字节的地址在指针变量中

定义指针变量

1
2
3
4
5
6
7
datatype *name;

datatype *name = value;

* 代表这是一个指针变量
datatype 表示指针变量指向的数据的类型
value 是指针,也就是数据地址。

实例

1
2
3
int a = 10; 
int *p = &a;
//p是一个指针变量,p指向一个int类型的数据(换句话说,p中存储的是一个int类型的数据的地址)

指针变量的大小是多少?

指针的大小在32位平台是4个字节,在64位平台是8个字节。

指针类型

1
2
3
4
5
6
7
8
9
10
char  *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;

//char* 类型的指针是为了存放 char 类型变量的地址。
//short* 类型的指针是为了存放 short 类型变量的地址。
//int* 类型的指针是为了存放 int 类型变量的地址。

1)秒判断出 指针的类型

只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。

1
2
3
4
5
int*ptr;         //指针的类型是int*
char*ptr; //指针的类型是char*
int**ptr; //指针的类型是int**
int(*ptr)[3]; //指针的类型是int(*)[3]
int*(*ptr)[4]; //指针的类型是int*(*)[4

2)秒判断出 指针所指向数据的类型

只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。

1
2
3
4
5
int*ptr;        //指针所指向的类型是int
char*ptr; //指针所指向的的类型是char
int**ptr; //指针所指向的的类型是int*
int(*ptr)[3]; //指针所指向的的类型是int()[3]
int*(*ptr)[4]; //指针所指向的的类型是int*()[4]

指针+-整数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int main()
{
int n = 10;
char a = 'a';
short n2 = '10';
char* pc = &a;
int* pi = &n;
short* ps = &n2;

printf("&a = %p\n", &a); // 输出a的地址
printf("pc = %p\n", pc); // pc为指针变量,存储的是a地址,输出结果同上
printf("pc+1 = %p\n", pc + 1); // pc+1为下一个元素的地址,输出结果在pc的基础上加了1

printf("&n = %p\n", &n); // 输出n的地址
printf("pi = %p\n", pi); // pi为指针变量,存储的是n地址,输出结果同上
printf("pi+1 = %p\n", pi + 1); // pi+1为下一个元素的地址,输出结果在pi的基础上加了4

printf("&n = %p\n", &n2); // 输出n2的地址
printf("pi = %p\n", ps); // ps为指针变量,存储的是n2地址,输出结果同上
printf("pi+1 = %p\n", ps + 1); // pi+1为下一个元素的地址,输出结果在pi的基础上加了2
return 0;
}

输出:
//&a = 00E7FAC7
//pc = 00E7FAC7
//pc+1 = 00E7FAC8
//&n = 00E7FAD0
//pi = 00E7FAD0
//pi+1 = 00E7FAD4
//&n = 00E7FAB8
//pi = 00E7FAB8
//pi+1 = 00E7FABA

以上代码得出:

指针的类型决定了指针向前或者向后走一步有多大(距离)。

指针的解引用

指针变量存储了数据的地址,通过指针变量能够获得该地址上的数据(根据门牌号找房间里的东西)

1
2
*pointer;
* 这里的*用来解引用

实例1

1
2
3
4
5
6
7
8
int main(){
int a = 10;
int *p = &a;
printf("%d, %d\n", a, *p); //两种方式都可以输出a的值
return 0;
}
输出:
//10, 10

实例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int main()
{
int n = 0x11223344;
char* pc = (char*)&n; // 这里不强制转换会警告
int* pi = &n;

printf("%p\n", pc); // pc是个指针变量,指向n的地址
printf("%p\n", pi); // pi是个指针变量,指向n的地址

printf("%#x\n", *pc);
printf("%#x\n", *pi);

*pc = 0; //重点在调试的过程中观察内存的变化。n中存储的数据变为0x11223300
printf("%#x\n", n);
n = 0x11223344;
*pi = 0; //重点在调试的过程中观察内存的变化。n中存储的数据变为0x00000000
printf("%#x\n", n);

return 0;
}

输出:
//007AFA98
//007AFA98
//0x44
//0x11223344
//0x11223300
//0

以上代码得出:

指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。

比如: char 的指针解引用就只能访问一个字节,而 int 的指针的解引用就能访问四个字节。

未完待续…