一个例子;
main()
{
int x=123;
}
所以,
x
是 int
类型变量和 2 个字节分配给 int
(目前的假设,这可能在机器方面有所不同。)比方说,地址
2000
和 2001
分配给 x
.那么,数据如何 123
使用这些地址存储?我是 C 的初学者,所以简单的语言会很有帮助。
我指的是 E Balagurusamy [Mc Graw Hill Education] 的“计算基础和 C 编程”。
最佳答案
当我考虑在 C 中存储变量时,我主要考虑的是与机器无关的盒子。所以给定
int x = 123;
我的第一个想法就是它看起来像这样:
+-----------+
x: | 123 |
+-----------+
由于这是一个局部变量,我知道这个小盒子在堆栈上。 (更多内容如下。)
现在,您询问了各个字节,并想象了一个从地址
int
开始的两字节 2000
。所以这就是更详细的外观。为了强调各个字节的内容,我将切换到十六进制: +------+
x: 2000: | 0x7b |
+------+
2001: | 0x00 |
+------+
您可能已经知道这一点,但该数字
0x7b
是 123
的十六进制表示的一部分。十进制数 123
具有十六进制表示 0x007b
。这确实假定了一个两字节整数,尽管值得注意的是,如今,您可能使用的大多数机器都将使用四个字节。我还展示了“小端”存储的情况,这是当今大多数机器使用的约定。编号较低的字节是最低有效字节。由于
123
实际上只是一个7位的数字,所以它只占用了两个字节中的一个,另一个为0。为了确保我们理解这两个字节的布局,假设我们为 x 分配了一个新值:x = 12345;
12345
的十六进制表示为 0x3039
,因此内存中的图片变为: +------+
x: 2000: | 0x39 |
+------+
2001: | 0x30 |
+------+
最后,为了比较,假设我说
long int y = 305419896;
并假设这是在具有相反的大端字节顺序的机器上。假设
long int
是四个字节,并且假设编译器选择将 y
放在地址 3000。那个看起来随机的数字 305419896
具有十六进制表示 0x12345678
,因此内存中的情况(再次假设大端字节顺序)看起来像这: +------+
y: 3000: | 0x12 |
+------+
3001: | 0x34 |
+------+
3002: | 0x56 |
+------+
3003: | 0x78 |
+------+
对于大端存储,低位地址包含最高有效字节,这意味着该数字在内存中从左到右(这里是从上到下)读取。但正如我所说,您今天可能使用的大多数机器都是小端的。
正如我所提到的,由于您示例中的
x
是一个局部变量,因此它通常存储在函数调用堆栈中。 (正如评论者所指出的,不能保证 C 甚至有一个堆栈,但大多数都有,所以让我们继续这个假设。)看看局部变量和全局变量之间的区别,并展示其他几个数据类型是如何存储,让我们看一个稍微大一点的例子,让我们扩大我们的范围来想象所有的内存。假设我写int g = 456;
char s[] = "hello";
int main() {
int x = 123;
char s2[] = "world";
char *p = s;
}
通常,全局变量存储在内存的下部,而堆栈存储在“顶部”,并且向下增长。所以我们可以想象我们的计算机的内存是这样的。正如您将看到的,我颠倒了我在前面图片中使用的约定。在这张图片中,内存地址在页面上运行。 (此外,内存地址现在也是十六进制的,并且我正在删除
0x
表示法。此外,我将回到 little-endian 字节顺序,但保留 16 位机器的概念。我也要去将字符值显示为它们本身,而不是十六进制。此外,我将未知字节显示为 ??
。) +------+
ffec: | ?? |
+------+
ffeb: | 00 |
+------+
x: ffea: | 7b |
+------+
ffe9: | 00 |
+------+
ffe8: | 'd' |
+------+
ffe7: | 'l' |
+------+
ffe6: | 'r' |
+------+
ffe5: | 'o' |
+------+
s2: ffe4: | 'w' |
+------+
ffe3: | 02 |
+------+
p: ffe2: | 80 |
+------+
ffe1: | ?? |
+------+
.
.
.
+------+
0282: | ?? |
+------+
0281: | 00 |
+------+
0280: | 'o' |
+------+
0283: | 'l' |
+------+
0282: | 'l' |
+------+
0281: | 'e' |
+------+
s: 0280: | 'h' |
+------+
0283: | 01 |
+------+
g: 0282: | c8 |
+------+
0281: | ?? |
+------+
当然,这是一个巨大的简化,但它应该给你一个基本的想法,尽管评论者忙于讨论所有深奥的可能并发症,但我仍然觉得以这种方式思考它很有用。下一步可能是展示
malloc
的内存看起来如何,以及当我们在堆栈上有几个函数调用处于事件状态时情况如何,但是这个答案太长了,所以我们将它保存到另一天。
关于c - 在 C 编程期间如何存储数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49443691/