c - 在 C 编程期间如何存储数据?

标签 c int storage

一个例子;

main()
{
    int x=123;
}

所以,xint类型变量和 2 个字节分配给 int (目前的假设,这可能在机器方面有所不同。)

比方说,地址20002001分配给 x .那么,数据如何 123使用这些地址存储?
我是 C 的初学者,所以简单的语言会很有帮助。

我指的是 E Balagurusamy [Mc Graw Hill Education] 的“计算基础和 C 编程”。

最佳答案

当我考虑在 C 中存储变量时,我主要考虑的是与机器无关的盒子。所以给定

int x = 123;

我的第一个想法就是它看起来像这样:
   +-----------+
x: |    123    |
   +-----------+

由于这是一个局部变量,我知道这个小盒子在堆栈上。 (更多内容如下。)

现在,您询问了各个字节,并想象了一个从地址 int 开始的两字节 2000。所以这就是更详细的外观。为了强调各个字节的内容,我将切换到十六进制:
         +------+
x: 2000: | 0x7b |
         +------+
   2001: | 0x00 |
         +------+

您可能已经知道这一点,但该数字 0x7b123 的十六进制表示的一部分。十进制数 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/

相关文章:

python - 为C编写Tensorflow模型

从一个字符指针复制到另一个字符指针

python - 我如何在 python 中将 int16 打包成字节

c - 对于非常大的整数值,我们如何将字符串转换为 int?

php - 用于在发送前收集数据的临时存储

azure - Azure 中的存储消耗报告

c - 尝试编译一个C程序

c++ - fopen 在 C++ 中使用 char * 出错

c++ - 将整数转换为字符串

java - requestLegacyExternalStorage 在 Android 11 - API 30 中不起作用