【问题标题】:Does char buf[100] allocate any memory?char buf[100] 是否分配任何内存?
【发布时间】:2021-04-10 10:46:31
【问题描述】:

char buf[100] 行是否在堆栈中分配任何内存?我假设它不是因为它只是一个声明。当我在运行下面两个不同的代码段后打印 buf 的地址时(一个用“test”填充 buf,另一个用“test test”填充),我得到不同的地址。这是否意味着buf实际上不是100字节,而在第一种情况下只有5个字节(空字符+1),在第二种情况下只有10个字节?

char buf[100]; 
strcpy(buf, "test");

对比

char buf[100]; 
strcpy(buf, "test test");

【问题讨论】:

  • “这只是一个声明”......不,这是一个定义。声明为extern char buf[100]; 如果多次运行同一个程序,每次运行可能会得到不同的地址。
  • strcpy 不分配内存
  • 差异的一个原因是地址空间随机化
  • 在块作用域中,每一个没有声明文件作用域对象(函数decl或extern对象decl)的声明也是一个定义。
  • @nquisitivemongoose 提供一个演示问题的最小完整程序。

标签: c memory


【解决方案1】:

C 标准使用抽象机器模型定义 C。当char buf[100]; 出现在函数中时,它在该抽象机器中定义 100 个char 的数组。从概念上讲,100 个字节是为该机器中的数组保留的,并且程序行为的所有描述都如同这 100 个字节是为数组保留的一样。

当 C 编译器实现具有此定义的程序时,不需要盲目地实现抽象机。它可以切掉机器不使用的部分。如果不使用全部 100 个字节,则允许编译器仅使用使程序工作实际需要的物理内存量。

为此,“工作”是指实际程序产生与抽象程序相同的可观察行为。可观察的行为包括输入/​​输出交互、对易失性对象的访问以及对文件的输出。如果编译器可以通过使用寄存器而不是主存来获得所需的可观察行为,那么它根本不必为数组使用主存。如果确实使用内存,则允许使用堆栈内存或其他内存。

在实践中,如果buf 的使用足够简单,编译器可以“看到”和“理解”您使用它所做的一切,它可能会消除部分或全部。如果您将buf 传递给当前翻译单元之外的另一个例程,编译器无法查看它是否真的被使用,因此它必须为其保留 100 个字节,通常在硬件堆栈上,以防其他例程使用实际使用所有buf。 (链接时优化可以实现跨多个翻译单元的优化,但这仍然是开发技术,不太可能消除在堆栈上分配这样的缓冲区——除非它可以看到你分配缓冲区的例程是不需要的,它可以完全消除常规。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    • 2016-07-31
    • 2019-04-22
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多