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

news/2024/11/29 13:35:51/

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

最近在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 via prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __userpointer sanitization
Vulnerability Spectre v2:        Mitigation; Enhanced IBRS, IBPB conditional, RSB filling
Vulnerability Srbds:             Mitigation; TSX disabled
Vulnerability Tsx async abort:   Mitigation; TSX disabled
标记:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adxsmap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d arch_capabilities

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


http://www.ppmy.cn/news/334847.html

相关文章

ARM嵌入式裸机简单使用

基于正点原子 ALPHA开发板,长文预警,建议收藏用到之后再查看 文章目录 主频与时钟I.MX6U系统时钟分析7路PLL时钟树外设如何选择时钟需要初始化的PLL和PFD I.MX6U系统配置系统主频的配置各个PLL时钟的配置其他外设时钟源配置 C代码 中断Cortex-A7中断系统…

性能优化-放开那片内存

性能优化是一个常有的事情,通常来说 不要过早优化-当你没有性能问题时,不需要过早考虑优化,当然对于一些代价很小,收益却很大的手段可以考虑做进来,例如最常见的就是根据业务需求选择合适的数据结构。 不要过度优化。…

《搜索和推荐中的深度匹配》——经典匹配模型 2.1 匹配学习

重磅推荐专栏: 《Transformers自然语言处理系列教程》 手把手带你深入实践Transformers,轻松构建属于自己的NLP智能应用! 2. 经典匹配模型 已经提出了使用传统的机器学习技术进行搜索中的查询文档匹配和推荐中的用户项目匹配的方法。这些方法…

详解如何使用 DosBox 安装 Windows 95 操作系统

其实博主最近想更的博文不是这个,原是想分享一个自己写的油猴插件帮助某网学员去绕过该网站限制拖在线课件及录播视频到本地保存的,但是,期间博主又动了重温经典游戏(博主想玩的游戏主要是生化危机、玩具兵大战、剑侠情缘等&#…

Linux CFS调度器分析

进程被调度的条件是什么,以及真正发生调度的时刻又是在哪里? 以下结论和代码分析都是基于最新Linux master分支(Linux5.0) 1. 调度的时刻 1.1 当前进程主动放弃CPU或者调用msleep/down/wait等阻塞函数时,会直接调用schedule()函数。 1.2. 当前进程满足…

进程管理基础学习笔记 - 3. schedule

目录 1. 前言2. __schedule|- -deactivate_task|- -pick_next_task|- -context_switch|- - -switch_to 参考文档 1. 前言 本专题我们开始学习进程管理部分。本文主要参考了《奔跑吧, Linux内核》、ULA、ULK的相关内容。本文只是作为学习笔记以用于构建知识框架,可能…

Linux内核进程创建-fork背后隐藏的技术细节(下)

上一篇文章我们讲到fork的时候内存管理相关的内容,时间大概隔了快一周了,发布下篇文章,写文章确实费时费力,需要仔细推敲,原创不易,希望大家多多支持吧。本文讲解fork的时候进程管理相关的内容,…

Machine Learning for Technical Debt Identification

目录 Abstract: 1 INTRODUCTION 2 RELATED WORK 3 METHODOLOGY 3.1 Data Collection 3.1.1 Project Selection and Dependent Variable 3.1.2 Analysis Tools and Independent Variables 3.2 Data Preparation 3.2.1 Data Pre-processing 3.2.2 Exploratory …