提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
我有一个问题,我似乎无法弄明白。 我希望有人能够彻底向我解释。 我觉得这很简单......
问题如下:
以下变量如何进入连续的内存地址及其值?
int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;
例如,
int8_t esim = 9;
将被存储为
0000:00001001
任何人?
我有一个问题,我似乎无法弄明白。 我希望有人能够彻底向我解释。 我认为这是非常基础的。
在这里你出错了。 这是非常基本的,但并不像你想象的那样
不同的变量不需要存储在内存中的连续位置。 (或者最后一颗子弹说,根本不存储在内存中)
多字节值中的单个字节的存储是实现定义的 - 检查编译器手册。 然而,现在大多数个人计算处理器都使用little-endian 2补码作为整数。
即使他们是由编译器组织在内存中出现,正是因为他们的声明相同的顺序,每个数据类型都需要实现特定的排列,因此在它是此对齐的倍数的地址只启动
最后,不需要任何变量或内存分配,编译器只需要生成一个程序, 就好像有这样的变量一样。
不过,我们当然可以说一下您的计划。 如果摘录
#include <stdint.h>
int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;
编译并将变量放在内存中
a
将为8位,值为0b01100101
c
将为16位并作为2个字节存储在存储器中 - 0b11001110
和0b01010110
在增加的存储器地址(little-endian,通常),或相同的2个字节反转: 0b01010110
和0b11001110
(big-endian)。 b
, 如果 执行字符集是ASCII兼容的,因为int8_t
存在,那么char
也必须是8位宽,然后它的值将被存储为0b01101011
(即107, k
的ASCII码)。 另外,大多数情况下uint16_t
对象的对齐要求是2; 如果是这种情况,它必须从偶数地址开始。
这种推论是唯一可能的,因为int8_t
和uint16_t
不能有填充位 ,因此通过它们我们可以推断出最小可寻址单元( char
)的宽度也必须是8位。 并且uint16_t
只有2个字节,因此它只能有两个字节序选择。
很容易测试GCC如何组织全局变量 。 考虑具有源代码的模块
#include <stdint.h>
int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;
我们可以将它编译成目标文件:
% gcc -c layouttest.c -o layouttest.o
然后使用nm
列出符号及其地址:
% nm layouttest.o
0000000000000000 D a
0000000000000001 D b
0000000000000002 D c
这似乎是Jabberwocky的答案所期望的。 如果我们现在使用-O3
编译,结果可能会有所不同:
% gcc -c layouttest.c -o layouttest.o -O3; nm layouttest.o
0000000000000003 D a
0000000000000002 D b
0000000000000000 D c
即变量被重新组织,底部是c
。
Antti Haapala答案的补充:
虽然完全取决于编译器如何以及在何处存储变量,但连续声明的变量的内存布局通常与声明顺序的顺序相同,尤其是在非优化代码中。
所以变量声明如下:
int8_t a = 0x65;
char b = 'k';
uint16_t c = 22222;
可以像这样存储:
Address Content in binary
--------------------------
0000: 01010101 (0x64)
0001: 01101011 ('k' = 107, ASCII code of k)
0002: 11001110 (low bits of 22222)
0003: 01010110 (high bits of 22222)
其中Address
是相对地址,带有对变量a
的内存地址的repsect。
再一次:不要认为这是您平台上必然的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.