【问题标题】:where does string literal passed to function call gets stored in c传递给函数调用的字符串文字在哪里存储在c中
【发布时间】:2013-11-09 03:49:34
【问题描述】:

我知道程序中使用的字符串文字会存储在只读区域中,例如。

//global
const char *s="Hello World \n";

这里的字符串文字 "Hello World\n" 存储在程序的只读区域中。 现在假设我在一些函数的主体中声明了一些文字,比如

func1(char *name)
{
    const char *s="Hello World\n";
}

由于函数的局部变量存储在该函数的激活记录中,这是 字符串文字也一样吗?再次假设我从某个函数 func2 调用 func1 为

func2()
{
    //code
    char *s="Mary\n";

    //call1
    func1(s);

    //call2
    func1("Charles");

    //code
}

在上面,在第一次从 func2 调用 func1 时,传递了“s”的起始地址,即 s[0] 的地址,而在第二次调用中,我不确定实际发生了什么。字符串文字“Charles”在哪里获得存储空间。编译器是否创建了一些tempory并传递了它的地址还是发生了其他事情? 我发现文字从“只读数据”部分存储 String literals: Where do they go? 但我不清楚这是否只发生在全局文字或某些函数的本地文字上。任何见解都将是可观的。谢谢。

【问题讨论】:

  • 我认为所有基于静态内存的值都存储在只读区域中,但要确定它的实际存储位置,您应该使用调试器逐步执行代码和/或打开可执行文件使用十六进制编辑器。
  • 尝试像“gcc -S -c file.c -o file.s”这样编译你的.c文件并查看file.s。在底部,您将看到一个包含所有字符串的“文本”部分。如果您仔细查看汇编代码,您可以看到它们是如何加载的。
  • 虽然gcc 确实如此,但另一个有趣的问题是,是否有任何标准对此有任何要求。

标签: c string literals


【解决方案1】:

字符串文字(或者更确切地说,它们被编译成的字符数组)在内存中的位置是编译器中的一个实现细节,因此,如果您正在考虑 C 标准所保证的内容,它们可能存在于许多地方,并且程序中以不同方式使用的字符串文字可能最终出现在不同的地方。

但在实践中,大多数编译器将所有字符串文字都视为相同,并且它们可能都以只读段结束。因此,用作函数参数或在函数内部使用的字符串字面量将与“全局”字面量存储在同一位置。

【讨论】:

  • 这是否意味着函数本地的字符串文字也会出现在只读文本段中?
  • 您的“答案”没有回答 OP 提出的问题,只有您随后的评论才能回答。事实上,你的答案是错误的;字符串文字不能“在任何地方”,特别是它们不能在堆栈上,因为它们具有静态存储持续时间。
  • @Jim Balter:是的,“任何地方”是错误的,或许应该改为“在多个地方,并且仍然符合标准”。我认为“将对所有字符串文字一视同仁”回答了这个问题。但我可能应该澄清一下。
  • @Jim Balter 我在 C 规范中找不到字符串文字不能在堆栈上。甚至在 C 规范中的任何地方都找不到“堆栈”。当然,字符串字面量需要具有静态存储持续时间,但实现方式似乎由实现定义。
  • @chux 它们具有静态存储持续时间暗示它们没有保存在函数堆栈帧中——这是一种实现机制,因此它们不会出现在标准。
【解决方案2】:

C 字符串字面量表示char[len+1] 类型的数组对象,其中len 是长度,加上1 表示终止'\0'。此数组对象具有静态存储持续时间,这意味着它存在于程序的整个执行过程中。无论字符串文字出现在何处,这都适用。

文字本身是一个表达式类型char[len+1]。 (在大多数但不是所有情况下,它将被隐式转换为指向第一个字符的 char* 值。)

编译器可以优化这一点,例如,只存储一次相同的字符串文字,或者如果它们从未被引用,则根本不存储它们。

如果你这样写:

const char *s="Hello World\n";

在函数内部,字面量的含义和我上面描述的一样。指针对象s被初始化为指向数组对象的第一个字符。

由于历史原因,字符串文字在 C 中不是 const,但尝试修改相应的数组对象具有未定义的行为。正如您在此处所做的那样,声明指针 const 不是必需的,但这是个好主意。

【讨论】:

  • 知道了。这意味着出现在函数调用中的文字也可以为整个程序执行获得静态存储。这似乎增加了所需的静态存储大小,因为我们可以在许多不同的函数和函数调用中使用许多文字,尽管许多函数可能并不总是被使用(在运行时调用)。
猜你喜欢
  • 2017-10-03
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 2017-12-05
  • 2017-03-21
  • 2013-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多