内存(在程序中称为主存DRAM)是计算机中重要的部件之一,它是外存(硬盘)与cpu进行沟通的桥梁.
计算机中所有的程序都是在内存中进行的,为了有效的使用内存,就把内存以8位二进制(bit)划分为存储单元(也就是1字节) ,为了有效的访问到内存的每个储存单元,就给内存进行了编号,这些编号被称为该内存存储单元的地址
当我们的程序进行编译,链接之后会生成一个可执行文件,这个可执行文件是储存在硬盘中的,在磁盘中的可执行文件不能运行,要想运行必须加载到主存储器中,包括可执行文件的代码,数据等都要放在主存储器中(实际上就是内存).cpu就会从内存中取得当前可执行文件的代码和数据.不可执行文件也必须从磁盘中加载到内存中
为什么它们不能从磁盘中读取呢?因为磁盘的读取速度太慢了
现在的计算机系统分为X86 32位系统 有32个地址线,每个地址都只能是0或1,想存放32个二进制位需要4字节 还有X64 64位系统
地址没有大小只有高低
想要访问某个内存单元必须要知道它的地址,每个内存的地址实际上就是编号
int main()
{
int a = 10;
char ch = 'a';
int* ip; //整形指针变量,*是一个声明,声明ip是一个指针变量(储存地址的变量)
char* cp;
ip = &a; //&是取地址符
cp = &ch;
printf("ip => %p &a => %p\n", ip, &a); //%p 输出地址
printf("cp => %p &ch => %p\n", cp, &ch);
return 0;
}
*的几个作用
int main()
{
int a = 10, b = 20, c = 0;
c = a * b; //这里*表示乘法
int* p; //p为指针变量,存放的是整型变量的地址,*代表声明
char* i; //i存放的是char类型变量的地址
p = &a;
*p; //*代表取的地址,*作为取地址运算符时,操作数(p)一定要是指针变量
*a; // a不是指针变量,编译不通过
int main()
{
int a = 10, b = 20;
int* p = NULL; //NULL为空指针,这步操作为把空指针赋给p
p = &a;
*p = 100;
p = &b;
*p = 200;
return 0;
}
接下来我们来详细分解一下,每一步骤地址空间取值变化
当定义完int *p = NULL;时,系统已经给a,b,p分配了空间和地址为:
a = 10
b = 20
&a = 0x006ffc8c
&b = 0x006ffc88
p = 0x00000000
&p = 0x006ffc84
当运行完int *p = NULL;
因为p是变量,为整型指针变量,我么会给指针开辟空间,再32位系统中,我们的指针占4个字节,在64位占8个字节
只要在内存中分配空间,那么都有物理地址的存在
运行到p = &a;
会把a的地址给p
此时
&p => 0x006ffc84
p => 0x006ffc8c ; 也就是a的地址&a
*p => a 可以把*p认为是a本身,又因为a = 10,所以*p取值取的是a的值,所以*p取的是10
指针有两个值,一个是p自身的值,在这里存放的是a的地址
另一个是指针指向的值*p,在这里也就是a本身。(一定重点理解)
运行到 *p = 100;
因为*p就是a本身,所以就相当于100赋值给a(取值语句*的优先级比赋值=高,赋值优先级只比逗号高)
运行到 p = &b;
此时&p => 0x006ffc84
p => 0x006ffc88
*p => b
简单来说就是p是b的地址,而*p就是指向的b本身
32位系统有四个字节,也就是4个存储单元,取地址取低地址,另三个储存单元也有地址
ip取的是a中的低的地址,也就是第一行
计算机的储存地址是小段储存,也就是低位数储存在低地址,高位数储存在高地址
像0x00AFFBA8 在储存时,
0x表示十六进制,高位数00储存在最下面高地址