17-1 内存
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。
为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
假如有一个32位的电脑:
有32根地址线;
产生电信号:1/0;
32根地址:
00000000000000000000000000000000 --->0
00000000000000000000000000000001 --->1
……
1111111111111111111111111111111111111
一共有2^32个地址序列,这么多的地址,一个地址管理一个内存单元,一个内存单元有1个字节,所以可以管理2^32字节的空间
clac,打开电脑上的计算机:
对2^32字节进行逐步换算:
综上:4,294,967,296 byte=4,194,304 kb=4,096 MB=4GB
计算机中的单位
bit-比特位-计算机中最小的单位
byte-字节 1byte=8bit
kb 1kb=1024byte
mb 1mb=1024kb
gb 1gb=1024mb
tb 1tb=1024gb
pb 1pb=1024tb
int main()
{
int a = 10; //向内存申请4个字节,存储10
return 0;
}
那么,a占4个字节,有4个地址,那么a的地址到底是哪一个呢?
我们应该找第一个地址,即首地址
我们来看一下吧:
调试查看a的地址:
调试查看内存:
输入&a,列选择4,便于查看
一行4个字节
左:地址
中:存放在内存里的数据
右:内存数据被解析得到的一些结果
十进制:0 1 2 3 4 5 6 7 8 9
八进制:0 1 2 3 4 5 6 7 8
十六进制:0 1 2 3 4 5 6 7 8 9 a b c d e f
a占32个bit位:
10的二进制:0000 0000 0000 0000 0000 0000 0000 1010
10的十六进制:0 0 0 0 0 0 0 a
即:0x 00 00 00 0a
在内存中是倒着存的(后续会讲原理)
综上,0x00000080668FF954地址存的就是10
17-2 指针变量和解引用
%p:以地址的格式打印的数据
我们来打印一下a的地址:
int main()
{
int a = 10; //向内存申请4个字节,存储10
printf("%p\n", &a);
return 0;
}
结果如下: (a的地址每次都会变)
最终结果呈现的是十六进制,因为十六进制易于展示
存储a的地址:
int main()
{
int a = 10;
int* p = &a;
return 0;
}
这里的p,就是指针变量
注意:
变量是p,不是*p;
类型是int*;
*,说明p是指针变量;
int说明p指向的对象是int类型。
内存单元->编号->地址->地址也被称为指针
存放指针(地址)的变量就是指针变量
图解:
int main()
{
int a = 10;
int* p = &a;
*p=20; //解引用操作符,意思就是通过p中存放的地址,找到p所指向的对象,*p就是p指向的对象
printf("%d\n", a); //其实*p就是a
return 0;
}
a的值被改变:
进一步解释:
&a //取地址a,找到a的地址
*p //解引用指针变量,找到指针变量指向的对象a
看一下内存里:
再次表明取的是首地址
17-3 指针的大小
不管是什么类型的指针,都是在创建指针变量
指针变量是用来存放地址的
指针变量的大小取决于一个地址存放的时候需要多大空间
32位机器上的地址:32bit位 - 4byte,所以指针变量的大小是4个字节(X86平台)
64位机器上的地址:64bit位 - 8byte,所以指针变量的大小是8个字节(X64平台)
X64平台:
测试代码:
int main()
{
printf("%zu\n", sizeof(char*));
printf("%zu\n", sizeof(short*));
printf("%zu\n", sizeof(int*));
printf("%zu\n", sizeof(float*));
printf("%zu\n", sizeof(double*));
return 0;
}
运行结果:
X86平台:
测试代码:
int main()
{
printf("%zu\n", sizeof(char*));
printf("%zu\n", sizeof(short*));
printf("%zu\n", sizeof(int*));
printf("%zu\n", sizeof(float*));
printf("%zu\n", sizeof(double*));
return 0;
}
运行结果:
17-4 不同的代码风格
以int*p举例:
第一种:int和*在一起
int main()
{
int a = 10;
int* p = &a;
return 0;
}
优势:清楚表明p的类型是int*
第二种:*和p在一起
int main()
{
int *a,b,c;
return 0;
}
优势:这个时候,其实只有a是int*类型的,而b和c都是int类型的,这样书写,更能清楚地表达各个变量的类型。如果想要a、b、c都是int*类型,那么应该:
int main()
{
int *a,*b,*c;
return 0;
}
所以,两种代码风格各有特色,采用哪种代码就要看个人习惯啦~~~