C++的一个指针占内存几个字节?
结论: 取决于是64位编译模式还是32位编译模式(注意,和机器位数没有直接关系)
- 在64位编译模式下,指针的占用内存大小是8字节
- 在32位编译模式下,指针占用内存大小是4字节
实验:(实验环境 vs2019)
- 64位编译模式下
64位编译模式下,sizeof返回的是unsigned long long类型,占8字节
- 32位编译模式下
32位编译模式下,sizeof返回的是unsgined int类型,占4字节
分析:
细心的同学可能会发现,为何 int* 和 stu* 类型的指针的大小一样呢?
- 因为指针的本身的值就是内存地址,它的占用字节数也就是该程序能够访问内存地址的空间大小,比如32位编译模式下,最大寻址为32位,2^32 B=4 GB,指针的值就是在 0x00000000 - 0xFFFFFFFF 范围内的值。因此指针本身占用的内存数和它指向的数据类型没有任何关系。
- 同理,64位编译模式下,理想的寻址位64位,也就是 2^64 B,这是个很大的值,而物理内存达不到这么大,CPU要实现64位的寻址能力只会增加系统复杂度和地址转换成本,因此Windows和Linux都做了限制,仅仅使用虚拟地址的48位,2^48 B=256TB。但是指针的占用内存字节数还是8 (只是Windows和Linux下,低48位有效而已).
额外讨论1:
那么,CPU寻址能力到底和什么有关呢?
答案是和地址总线的数量有关。
- 16位CPU
早期的CPU是16位的,一次能处理 16Bit(2个字节)的数据。这个时候计算机产业还处在早期,个人电脑也没有进入千家万户,也没有提出虚拟地址的概念,程序还是直接运行在物理内存上。典型的16位处理器是 Intel 8086,它的数据总线有16根,地址总线有20根,寻址能力为 2^20 B = 1MB - 32位CPU
随着计算机产业的进步,出现了32位的CPU,一次能处理 32Bit(4个字节)的数据。这个时候就提出了虚拟地址的概念,并被应用到CPU和操作系统中,由它们共同完成虚拟地址和物理地址的映射。典型的32位处理器是 Intel 的 80386 和 Intel Pentium 4(奔腾4):80386 的数据总线和地址总线宽度都是32位,寻址能力达4GB;Pentium 4的地址总线宽度是36位,理论寻址能力达64GB。 - 64位CPU
现在64位的CPU也普及到千家万户,它们一次能处理64Bit(8个字节)的数据。典型的64位处理器是 Intel 的 Core i3、i5、i7 等,它们的地址总线宽度为 40~50 位左右。
值得注意的是,支持多大的寻址空间和CPU的位数没有直接关系,CPU的位数是指寄存器的位数,也可以说是数据总线的数量,衡量的是单次处理数据的能力。一般来说,地址总线会随着数据总线增多,也随之增多,用以支持更大的寻址空间。
额外讨论2:
short, int, long, long long在32位编译模式下和64编译模式下,占多少字节?
结论: 一样的!
short | int | long | long long | __int64 | |
---|---|---|---|---|---|
32位 | 2 | 4 | 4 | 8 | 8 |
64位 | 2 | 4 | 4 | 8 | 8 |
实验:
- 64位
- 32位