【问题标题】:data structures allocated at compile time?编译时分配的数据结构?
【发布时间】:2020-08-10 13:13:42
【问题描述】:

我想我有一堆愚蠢的问题一直困扰着我,我无法在任何地方找到令人满意的答案,所以还不如在这里问并被看不起,而不是让它在我的脑海中漂浮。我会直接说的。

  1. 如果我在函数内部有一些变量和数组(其大小在编译时已知),如果根本不调用该函数,它是否仍然被分配?

  2. 这与 .c 文件和 .out 可执行文件的大小有何关系?

  3. 我在哪里可以找到这样的东西?你知道,一些很好的编程书籍,不仅教授语言,还教授内存中的基本工作原理。

【问题讨论】:

  • 1.不,假设它们是局部变量 - 输入函数时将分配空间。 2. 代码仍然是可执行的,因此它们会导致 *.c 的大小和 *.exe(或 *.out)的大小。 3. 也许一本关于汇编编程的好书,也许“链接器和加载器”可能是一个起点
  • Brian Kernighan 和 Denis Ritchie 合着的《C 编程语言》是一本很好的 C 编程参考书。

标签: c memory-management compile-time


【解决方案1】:
  1. 如果我有一些变量和数组(其大小在编译时已知),在函数内部,如果函数没有分配,它是否仍被分配 完全调用了吗?

规范是怎么说的

如果您在函数中声明 static 对象,那么它们就存在并在程序的整个生命周期内保留它们的值。每个这样的变量只有一个副本,无论函数被调用多少次,甚至无论并发和递归调用如何。

如果您在函数内声明非static 对象,则最里面的包含块的每个执行都会获得每个副本,并且每个这样的副本在与其关联的块执行终止时不再存在。

您在实践中可能会看到什么

C 实现在许多方面都可以偏离规范的细节,只要它们产生与完全遵循规范一样的可观察行为。您可能会看到的差异包括

  • 如果编译器确定无法调用给定函数,则可以省略整个函数以及它声明的任何变量。

  • 如果编译器确定给定变量永远无法读取,则可能会完全省略该变量以及对它的任何写入(除非它是 volatile)。

  • 原则上,程序可能不会分配或初始化静态变量,直到它们第一次被访问(虽然这不太可能)。

  • 尾递归函数调用可以折叠成迭代,这样函数的局部变量就可以重复使用,而不是为每个递归调用创建新变量。

  1. 这与 .c 文件和 .out 可执行文件的大小有何关系?

.c 源文件由您编写的代码组成。如果您编写更多代码,则它会更大。如果你写的代码越少,那么它就越小。

也许您的意思是目标文件(按 Unix 约定为 .o)。规范在这里没有谈到这个问题,甚至根本没有直接谈到这些文件。在实践中,实现会有所不同,但在编译器保留的所有局部变量中,只有那些 static 并使用非零初始化器声明的变量才会占用目标文件、二进制库或可执行文件中的空间。

  1. 我在哪里可以找到这样的东西?你知道的,一些很好的编程书籍,不仅教语言,还教底层 记忆中的工作原理。

很抱歉,这部分问题与 Stack Overflow 无关。我们不会解决为非现场材料征求建议的问题,包括但不限于教科书和教程。

【讨论】:

    【解决方案2】:

    如果你已经用大小声明了你的变量,比如

    int a[10];
    

    这意味着内存将从堆栈中使用。这是在编译时分配的(静态)。

    通常,如果您不调用函数,编译器的预处理器会消除该代码。所以你可能不会仅仅因为你的编译器很聪明而注意到内存使用的差异。

    .C 和 .OUT 文件只是带有命令的文件,不会受到内存声明的影响。但是,如果你的代码中有类似宏的东西,这可能会在编译后增加大小。你可以阅读内存管理器,动态和静态内存(堆和栈)得到很好的理解

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-07
      • 2012-06-26
      • 2021-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-06
      相关资源
      最近更新 更多