linux 64位系统 printf(“%p“)显示12个字符解惑

本人非计算机专业,写给自己只为弄清楚这个问题 

最近在64位linux系统中打印地址,代码如下

int a = 1;
int *p = &a;
printf("%d\n", sizeof(p));
printf("%p\n", p);

结果为

8
0x7ffea2cabb3c

这就引起我的好奇心了,64位系统应该打印16个字符才对,这里只有12个

我们研究一下sizeof和内存地址为什么是上边打印的这两个东西

我们先来看8位系统中内存表示(8个格,1格1位,1位可以有0和1两种表示),然后再推论64位

11111111

 

 

众所周知 1字节=8bit=8位

sizeof(p) = 系统位数/8;

那么这个8位系统的指针存放地址的字节大小sizeof(p)应该等于1

相应的32位系统地址字节大小sizeof = 4,64位系统地址字节大小sizeof = 8


再来看地址,上边8个格子里表示的内存,最小为00000000=0,最大为11111111=255;

转换为十六进制表示是0x00-0xFF

所以打印出来应该是2个字符,如0xab

那么32位地址打印应该是4*2,8个字符,如0xabababab这样,事实上实验也是这样的

而64位打印出来应该是16个字符,可实际上打印出来只有12个字符

查了查原因,感觉知乎@Rednaxela回答比较专业,这里进行引用

作者:RednaxelaFX
链接:https://www.zhihu.com/question/28638698/answer/41603886
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

假定题主问的只是AMD64。Intel版叫做Intel® 64,是从AMD交叉授权来的AMD64;Intel® 64曾用名EM64T。

当前版本的AMD64架构就规定了只用48位地址;一个表示虚拟内存地址的64位指针只有低48位有效并带符号扩展到64位——换句话说,其高16位必须是全1或全0,而且必须与低48位的最高位(第47位)一致,否则通过该地址访问内存会产生#GP异常(general-protection exception)。

只用48位的原因很简单:因为现在还用不到完整的64位寻址空间,所以硬件也没必要支持那么多位的地址。
设计为带符号扩展的原因也很简单:很多环境中,寻址空间的高一半(higher-half)有特殊用途,而低一半(lower-half)给用户做一般用途。这“高/低”可以通过最高位是1还是0来判断;如果把地址看成带符号整数,那么“负数”部分就是高一半,“正数”部分就是低一半。所以AMD64在设计成只用64位中的48位时,要求canonical form要满足带符号扩展的要求。以后就算允许更多位地址,满足当前限制的地址也仍然会是合法地址,保证了向前兼容性。

这些限制都只是临时的。以后真的需要的时候可以放宽到52位,最终时机到的时候就会扩展到真正的完整64位吧。

===============================================

其它64位CPU架构未必有一样的限制。
SPARC的64位版就允许完整的64位寻址空间。
AArch64允许用高8位来做tag,那么还有56位寻址空间。
既然题主问的是48位那多半是AMD64吧⋯

 

再linux上进行操作

lscpu
架构:                           x86_64
CPU 运行模式:                   32-bit, 64-bit
字节序:                         Little Endian
Address sizes:                   39 bits physical, 48 bits virtual
CPU:                             8
在线 CPU 列表:                  0-7
每个核的线程数:                 1
每个座的核数:                   8
座:                             1
NUMA 节点:                      1
厂商 ID:                        GenuineIntel
CPU 系列:                       6
型号:                           158
型号名称:                       Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
步进:                           13
CPU MHz:                        800.014
CPU 最大 MHz:                   4700.0000
CPU 最小 MHz:                   800.0000
BogoMIPS:                       6000.00
虚拟化:                         VT-x
L1d 缓存:                       256 KiB
L1i 缓存:                       256 KiB
L2 缓存:                        2 MiB
L3 缓存:                        12 MiB
NUMA 节点0 CPU:                 0-7
Vulnerability Itlb multihit:     KVM: Mitigation: Split huge pages
Vulnerability L1tf:              Not affected
Vulnerability Mds:               Not affected
Vulnerability Meltdown:          Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled v
                                 ia prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user
                                  pointer sanitization
Vulnerability Spectre v2:        Mitigation; Enhanced IBRS, IBPB conditional, RS
                                 B filling
Vulnerability Srbds:             Mitigation; TSX disabled
Vulnerability Tsx async abort:   Mitigation; TSX disabled
标记:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtr
                                 r pge mca cmov pat pse36 clflush dts acpi mmx f
                                 xsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rd
                                 tscp lm constant_tsc art arch_perfmon pebs bts 
                                 rep_good nopl xtopology nonstop_tsc cpuid aperf
                                 mperf pni pclmulqdq dtes64 monitor ds_cpl vmx s
                                 mx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid s
                                 se4_1 sse4_2 x2apic movbe popcnt tsc_deadline_t
                                 imer aes xsave avx f16c rdrand lahf_lm abm 3dno
                                 wprefetch cpuid_fault epb invpcid_single ssbd i
                                 brs ibpb stibp ibrs_enhanced tpr_shadow vnmi fl
                                 expriority ept vpid ept_ad fsgsbase tsc_adjust 
                                 bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx
                                  smap clflushopt intel_pt xsaveopt xsavec xgetb
                                 v1 xsaves dtherm ida arat pln pts hwp hwp_notif
                                 y hwp_act_window hwp_epp md_clear flush_l1d arc
                                 h_capabilities

可以看到虚存有48bits,这也就说明为啥一开始打印的字符数是12个,8位系统2个字符,48位当然是12个啦

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值