在64位计算机上,我们知道地址是8个字节。 但是,我不完全清楚一个地址中有多少字节的信息。 虚拟内存中的每个字节都有地址吗?还是内存中的每个64位都有一个地址? 还是取决于架构?如果取决于体系结构,那我应该如何找出?
答案 0 :(得分:3)
在C中,char
是最小的可寻址单元。 (通常映射到最小的asm可寻址单元,但不能保证 1 。)limits.h中的CHAR_BIT
告诉您它有多少位。通常是8
,但从历史上看,有些机器的字节和字长都不是2的幂。
在asm中,大多数现代ISA都是字节寻址的,但是现代DSP有时也可以是字寻址的,因为它们关心的唯一代码是处理整数或浮点数据的代码,而不是字符串。
如果取决于体系结构,那我应该如何找出?
这是您从ISA手册中找到的内容,以及其他基本信息,例如寄存器名称及其宽度。这是机器语言的固有属性。
脚注1:
您可以想象一个奇怪的假设ISA,它可以按字节寻址,但是在其中字节存储可以实现为包含(32位)字的 non-atomic 读-修改-写操作。要么是硬件(极其不寻常),要么是软件(实际上已经发生)。
例如,DEC Alpha AXP(90年代的RISC ISA,为高性能和64位而积极设计的)的前几个版本具有字节可寻址内存,但是最窄的加载/存储是32位。
因此每个字节都有其自己的地址,但是没有硬件指令修改单个字节。如果当时的C实现使用CHAR_BIT=8
,则他们必须使用软件加载/合并/存储来模拟char
分配,除非他们知道这是一个带有填充的char
对象(例如本地或全局),他们可以覆盖这些填充。
现代C11实现在将CHAR_BIT=32
引用为左值时必须使用char*
或使用慢速LL / SC重试循环来原子替换字节,因为C11引入了一种不不允许发明C抽象机中不会发生的写操作(例如读取和以后重写相同的数据)。这可能会破坏单独线程在其中写入相邻数据的代码。请参阅C++ memory model and race conditions on char arrays(在这方面C11内存模型与C ++ 11相匹配)。
另请参阅Can modern x86 hardware not store a single byte to memory?,以获取更多详细信息,而不仅仅是x86。
后来的Alpha模型引入了字节和半字加载/存储指令,因此编译器可以使用它们来实现有效的C11实现,并使用一个字节的char
。
答案 1 :(得分:3)
您的问题与this one有关。
还是取决于体系结构?
是的。这取决于架构:
对于大多数CPU ,一个地址表示 8位。
内存中的每个字节都有一个单独的地址。
TMS320 DSP 是一个CPU的示例,其中一个地址表示 16位。
这意味着内存中的每个16位字(uint16
)都有一个单独的地址。
还有一些计算机(其中许多都是历史悠久的),其中每个地址代表 12 , 13 , 14 , 16 , 24 或 36位(甚至更多)...
(不幸的是,我不知道使用64位地址而不是每个地址使用8位的CPU的示例,但是我很确定也存在这样的CPU。)
然后存在并非所有地址存在的内存类型。看起来可能是这样的:
可被4整除的地址表示 32位信息;其他地址无法使用-这意味着这些地址完全表示没有信息。
因此,地址的“平均值”是8位,但是没有地址表示8位。
通常,在安装了两种不同类型的内存的计算机中会看到这种现象,并且一种类型同时允许8位和32位访问,而另一种类型只允许32位访问。
外围设备的存储器通常是这种情况,例如某些微控制器中以太网控制器的存储器。
据我所记得,我已经看到用于PC的PCI SCSI控制器也显示了此行为。将SCSI控制器安装到64位计算机中,并且计算机包含一定范围的地址,其中所有地址的25%代表32位数据,而所有地址的75%根本不代表任何数据。
我还看到过大学学生设计的CPU,其中“商业原版”允许对内存进行8位和32位访问,而学生的副本仅对32位进行访问。在这种情况下,整个地址范围都会显示此行为。
顺便说一句:
在64位计算机上,我们知道地址为8个字节。
即使这不一定是真的:
据我所知,x86-64 CPU仅使用48位地址。因此,编译器制造商可以将每个地址仅存储在6个字节的内存中。
当然,嵌入式设备的CPU内核可以设计为使用x86-64指令集的子集,但是通常保存地址(例如rsp
)的寄存器只有48位宽。
答案 2 :(得分:-2)
您可以通过更改变量来检查地址的更改方式。
cout<<sizeof(char)<<endl;
char ch[3];
cout<<ch[0]<<" "<<std::hex<< (long)(char*)(&ch[0])<<" "<<ch[1]<<" "<<(long)(char*)(&ch[1])<<" "<<ch[2]<<" "<<(long)(char*)(&ch[2])<<endl;
答案 3 :(得分:-2)
Peter&ch [1]不起作用,但是ch是一个char指针,因此您可以在其上继续加+1以获取数组中的下一个char。 作为证明:
cout<<sizeof(char)<<endl;
char ch[3]={55,33,70};
char *chp1=ch;
cout<<chp1<<" "<<&(chp1)<<" ";
char *chp2=ch+1;
cout<<chp2<<" "<<&(chp2)<<" ";
char *chp3=ch+2;
cout<<chp3<<" "<<&(chp3)<<endl;
return 0;
12月55日为7点 33是! 70是F https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html 它们被计算为7!F,!F,F,因为字符数组被计算为空格。如您所见,指针指向上述数组的下一个字符。输出:i.stack.imgur.com/pBot5.jpg
cout<<sizeof(char)<<endl;
char ch[3]={55,33,70};
char *chp1=ch;
cout <<ch[0]<<" "<< (void*)(&ch[0])<<" "<<ch[1]<<" "<<(void*)(&ch[1])<<" "<<ch[2]<<" "<<(void*)(&ch[2])<<endl;