一、内存和地址
1byte(字节) = 8bit(比特位)
1KB = 1024byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TB
一个比特位可以存放二进制的0/1的一位
⽣活中我们把门牌号也叫地址,在计算机中我们把内存单元的编号也称为地址。C语言中给地址起了新的名字叫:指针。
所以我们可以理解为:内存单元的编号 == 地址 == 指针
二、指针变量和地址
1、指针变量
指针变量也是⼀种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会理解为地址。
2、拆解指针类型
我们看到pa的类型是 int* ,我们该如何理解指针的类型呢?
int a = 10;
int* pa = &a;
这里 pa 左边写的是 int* , * 是在说明pa是指针变量,而前面的 int 是在说明pa指向的是整型(int)类型的对象。
3、解引用操作符
只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)指向的对象,这里必须学习⼀个操作符叫解引用操作符(*)。
#include <stdio.h>
int main()
{
int a = 100;
int* pa = &a;
*pa = 0;
return 0;
}
上面代码中第7行就使用了解引用操作符, *pa 的意思就是通过pa中存放的地址,找到指向的空间,*pa其实就是a变量;所以*pa = 0,这个操作符是把a改成了0。
其实这⾥是把a的修改交给了pa来操作,这样对a的修改,就多了⼀种的途径,写代码就会更加灵活。
4、指针变量的大小
32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或者0,那我们把32根地址线产⽣的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4个字节才能存储。如果指针变量是⽤来存放地址的,那么指针变的⼤⼩就得是4个字节的空间才可以。
同理64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要8个字节的空间,指针变的大小就是8个字节。
32位
64位
总结:
• 32位平台下地址是32个bit位,指针变量大小是4个字节;
• 64位平台下地址是64个bit位,指针变量大小是8个字节;
• 注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。
三、指针变量类型的意义
指针变量的⼤⼩和类型⽆关,只要是指针变量,在同⼀个平台下,大小都是⼀样的,为什么还要有各种各样的指针类型呢?
1、指针的解引用
对⽐,下⾯2段代码,主要在调试时观察内存的变化
//代码1
#include <stdio.h>
int main()
{
int n = 0x11223344;
int* pi = &n;
*pi = 0;
return 0;
}
//代码2
#include <stdio.h>
int main()
{
int n = 0x11223344;
char* pc = (char*)&n;
*pc = 0;
return 0;
}
调试我们可以看到,代码1会将n的4个字节全部改为0,但是代码2只是将n的第⼀个字节改为0。
结论:指针的类型决定了,对指针解引用的时候有多大的权限(一次能操作几个字节)。
意思就是 char* 的指针解引⽤就只能访问⼀个字节,而int* 的指针的解引⽤就能访问四个字节,同理short* 访问2个字节 double* 就会访问8个字节。
2、指针 + - 整数
先看⼀段代码,调试观察地址的变化。
#include <stdio.h>
int main()
{
int n = 10;
char* pc = (char*)&n;
int* pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc + 1);
printf("%p\n", pi)