3

假设我有一个具有以下规范的函数:

void example(char* str)

如果我传入一个字符串参数,例如:

example("testing");

“测试”的值是在堆上动态分配的,所以我可以在对“示例”进行函数调用的范围被破坏(并且需要稍后释放它)之后使用它,或者它是本地的堆栈上的变量,所以我需要使用 malloc 创建一个新字符串并将值存储在其中,如果我希望它持久存在,比如说,哈希图?

谢谢。

4

3 回答 3

8

When you write "testing" in your program, it will be compiled as a string literal, and room for it will be allocated during compile time. When you get a pointer to it, it's a pointer to that place in memory. You don't need to allocate it with malloc(), and you also should not free() it. But it's also not a good idea to try to modify its content, because the compiler will likely put it in a readonly area (that is, it's compiled as a constant) -- the following program, for example, crashes on my Linux desktop:

#include <stdio.h>
int main() {
    char *a = "abc\n";
    a[0]='X';
    printf(a);
    return(0);
}
于 2013-07-02T03:33:08.707 回答
3

在 C 中,引号之间的字符串“例如 this”称为字符串文字

字符串文字,例如你上面给出的,不是动态分配的。通常,它们在编译和/或链接时分配,并且可能分配在只读内存中。(这就是为什么在 C++ 中,字符串文字与 .const char相对char。)

在幕后,一些编译器将“测试”存储在字符串表中,生成指向它的特殊指针。它大致相当于:

char *const compiler_generated_pointer_to_testing = (char *) (compiler_generated_string_table + 12345);

...

const char compiler_generated_string_table[] = { 
    ...
    't', 'e', 's', 't', 'i', 'n', 'g', 0, 
    ...
};

...

example( compiler_generated_pointer_to_testing );

这是它可以发挥作用的一种方式。许多其他实现是合法的。无论如何,实现细节可能不是重点。要记住的真正要点是:

  • 编译时字符串文字应被视为const,即使编译器不要求您将指向它们的指针声明为const char *.
  • 它们在编译和/或链接时分配,而不是在堆或堆栈上。
  • 不能保证相同字符串的两个实例(即在程序foo("testing")bar("testing")不同部分)是不同的指针,也不保证它们是相同的指针值。
  • 您绝不能free()使用字符串文字。
  • 您绝不能写入字符串文字。
  • 字符串文字将在程序的整个生命周期中保持可用,因此它可以作为哈希键正常工作。

明白了吗?任何问题?

于 2013-07-02T03:39:21.280 回答
1

最常见的是,它将作为字符串文字存储在可执行文件的只读部分中。您实际上可以通过使用-S标志编译程序来手动验证这一点。

它将生成一个名为的程序集可执行文件name_of_your_app.s,您可以在其中找到字符串文字(它将位于所谓的数据段中)。

有时,编译器可以放入代码段,或者根据优化级别,它会简单地将其优化掉(最容易通过创建一个不在任何地方使用的字符串文字然后使用-O3GCC 上的标志进行编译来检查)。

这是一个(人为的)示例:

int main() 
{
    char *a = "Hai!";

    return 0; 
}

如果我在没有特殊标志的情况下编译它,则字符串文字仍然存在:

$ gcc -S main.c
main.c: In function ‘main’:
main.c:9:11: warning: unused variable ‘a’ [-Wunused-variable]
$ cat main.s | grep Hai
    .string "Hai!"

但是,一旦我提高了优化级别,情况就不再如此:

$ gcc -S -O3 main.c
main.c: In function ‘main’:
main.c:9:11: warning: unused variable ‘a’ [-Wunused-variable]
$ cat main.s | grep Hai
$

看起来这个答案解决了同样的问题。

于 2013-07-02T03:36:39.737 回答