理解指针(1)
- 1·什么是内存
- 2·指针变量和地址
- 2·1 取地址操作符(&)
- 2·2 指针变量
- 2·3 解引用操作符(*)
- 2·4 指针变量的大小
- 3·指针变量的意义
- 3·1指针的解引用
- 3·2 指针加减整数
- 3·3 void* 指针
- 4. const 修饰指针
- 4·1 const 修饰变量
- 4·2 const 修饰指针变量
1·什么是内存
我们知道计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,其实也是把内存划分为⼀个个的内存单元,每个内存单元的⼤⼩取1个字节。每个内存单元也都有⼀个编号有了这个内存单元的编号,CPU就可以快速找到一个内存空间。
在计算机中我们把内存单元的编号也称为地址。C语⾔中给地址起了新的名字叫:指针。
所以我们可以理解为:
内存单元的编号=地址=指针
2·指针变量和地址
2·1 取地址操作符(&)
比如,我们现在创建一个整形变量n,想要知道n的地址,就可以用到取地址操作符。
#include<stdio.h>
int main()
{int n = 20;printf("%p", &n);return 0;
}
这里的&n
就是取出n的地址,%p
是算地址的操作符。
最后我们可以获得 n的地址:
&n
取出的是a所占4个字节中地址较小的字节的地址。
2·2 指针变量
当我们通过取地址操作符拿到的地址是一个数值,这时候我们需要把这个数值储存起
来就需要储存在指针变量中。
#include<stdio.h>
int main()
{int a = 20;int* p = &a; //取出a的地址储存在指针变量p中return 0;
}
指针变量也是变量,用来存放地址的。
我们看上面的例子,p
的类型是int *
,*
说明p是指针变量,而int
说明p
是指向整形类型的对象。
2·3 解引用操作符(*)
C语⾔中,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)指向的对象。因此需要用到解引用操作符(*)。
#include<stdio.h>
int main()
{int a = 20;int* p = &a;printf("%d\n", a);*p = 30;printf("%d\n", a);return 0;
}
*p
是指通过p存放的地址,找到指向的空间。*p
其实就是a变量,由例子可以直观的看出,当没有*p = 30;
这一行之前,a的值就是20,当给*p
重新赋值后,a的值就发生了改变,由这个我们也可以得出*p=a
这个结论。
2·4 指针变量的大小
• 32位平台下地址是32个bit位,指针变量⼤⼩是4个字节。
• 64位平台下地址是64个bit位,指针变量⼤⼩是8个字节。
同样的代码在不同的平台下,指针变量大小都不一样,由此我们可以知道 :指针变量的⼤⼩和类型是⽆关的,只要指针类型的变量,在相同的平台下,大小都是相同的。
3·指针变量的意义
3·1指针的解引用
上面两个例子,我们经过调试后可以发现左边的例子将a的4个字节全部改为1,而右边
的例子将a的一个字节改为了1,所以我们可以得到一个结论:指针的类型决定了,对
指针解引用的时候有多大的权限(⼀次能操作几个字节)。
3·2 指针加减整数
#include<stdio.h>
int main()
{int a = 20;int* p = &a;char* pa = (char)&a;printf("%p\n", p);printf("%p\n", p+1);printf("%p\n", pa);printf("%p\n", pa+ 1);return 0;
}
上面的例子是指针类型差异带来的变化。结论:指针的类型决定了指针向前或者向后走⼀步有多大(距离)。
3·3 void* 指针
这种类型的指针可以⽤来接受任意类型地址。
但是也有局限性, void*
类型的指针不能直接进行指针的**±整数**和解引用的运算。
#include<stdio.h>
int main()
{int a = 10;int* p = &a;char* pa = &a;return 0;
}
我们可以看到错误原因,但是我们使用void*
类型就不会有这个错误原因。
#include<stdio.h>
int main()
{int a = 10;void* p = &a;void* pa = &a;*p = 20;*pa = 0;return 0;
}
由上面两个例子我们可以知道 void*
类型的指针可以接收不同类型的地址,但是无法直接进行指针运算。
4. const 修饰指针
4·1 const 修饰变量
变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变量。
但如果我们想要给变量加上一些限制,不让它被修改,这样的话,我们就可以用到const
。
因为const已经给m加上限制了,所以,m不能像上面的n 那样重新赋值。
4·2 const 修饰指针变量
将const 放在*左边和右边的意义都不一样。
int const * p=&a;//放在*左边
int* const p=&a;//放在*右边
当我们把*放在左边:
const
如果放在*
的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
const
如果放在*
的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。
(由于指针的内容很多,所以后期还会用的。(。•ˇ‸ˇ•。)!!!)