参考文章
地址
地址是内存中每个字节的编号。
假设现有一个 4G
容量的内存,换算成字节为:
4G = 4 * 1024 * 1024 * 1024 = 4294967296 Byte
由于地址是从 0 开始算的,所以其能够表示的范围(十进制)为 0 - 4294967295
。
在计算机领域内不会使用10进制,而是使用二进制,范围为:
0000 0000 0000 0000 0000 0000 0000 0000<->1111 1111 1111 1111 1111 1111 1111 1111
为什么用如上的方式表示呢??而不是用 0 - 1111 1111 1111 1111 1111 1111 1111 1111
来表示呢??实际这么做也是可以的!不过最好推荐是使用如上的方式表示,为什么这么推荐呢??例如现在有一个 1000 人参赛的赛场,需要对参赛的 1000 人分配编号,你会怎么分配??是使用 0 - 999
进行分配还是使用 000 - 999
进行分配??肯定是使用 000 - 999
进行分配吧,同理可得。
但显然使用二进制的方式表示足足有 32bit
的长度!!太长了,所以人们实际上使用的是16进制来表示地址!范围是:
0x00000000 <-> 0xFFFFFFFF
指针
指针是保存地址的变量
联系
地址可以保存在指针中;指针仅保存地址。
区别
地址是字节编号,是一串 16进制 数字;指针是保存地址的变量。
使用地址的范例
int a[3] = {1 , 2 , 3};// 由于 a 变量存在 main 函数内// 所以是存储在 栈区 的局部变量// 在函数调用完毕后会被释放(取消内存占用,// 该片内存区域可被任意修改)// 程序结束时被 os 回收// 下次调用时,栈会被重建,所以变量// 对应的内存地址也会发生变化// 所以,这边仅展示某一次运行时的结果// 以下结果是某次运行时的结果.printf("&a[0] = %p\n" , &a[0]); // 000000218F4FF768printf("&a[1] = %p\n" , &a[1]); // 000000218F4FF76Cprintf("&a[2] = %p\n" , &a[2]); // 000000218F4FF770
从这边可以发现数组相邻元素地址相差 4
,通过上述对地址的认知后,可以理解:
地址表示的是内存字节的编号。&a[0]
表示的是 数组a
第一个元素第一个字节的编号 000000218F4FF768
,&a[1]
是数组a
第二个元素第一个字节的编号 000000218F4FF76C
,他们相差 4
。
为什么是相差 4
呢??这个是 4
有什么含义吗??
我们都知道无论是 32bit/64bit
系统中,int
占 4 Byte
,而地址表示的字节编号,所以有:
a[0] 第一个字节编号 000000218F4FF768a[0] 第二个字节编号 000000218F4FF769a[0] 第三个字节编号 000000218F4FF76Aa[0] 第四个字节编号 000000218F4FF76Ba[1] 第一个字节编号 000000218F4FF76Ca[1] 第二个字节编号 000000218F4FF76Da[1] 第三个字节编号 000000218F4FF76Ea[1] 第四个字节编号 000000218F4FF76F
由上可知他们必然会相差 4
,这个相差 4 没有什么特别的含义,就是在编号上相差 4 的意思。
使用指针的范例
int a[3] = {1 , 2 , 3};int *p_a = a;printf("p_a + 0 = %p\n" , p_a); // 000000218F4FF768printf("p_a + 1 = %p\n" , p_a); // 000000218F4FF76Cprintf("p_a + 2 = %p\n" , p_a); // 000000218F4FF770
这边要理解下指针运算,p_a + 0
,在地址体现上是 p_a + 0 * sizeof(int)
。
其他同地址范例。