假设我有一个具有以下规范的函数:
void example(char* str)
如果我传入一个字符串参数,例如:
example("testing");
“测试”的值是在堆上动态分配的,所以我可以在对“示例”进行函数调用的范围被破坏(并且需要稍后释放它)之后使用它,或者它是本地的堆栈上的变量,所以我需要使用 malloc 创建一个新字符串并将值存储在其中,如果我希望它持久存在,比如说,哈希图?
谢谢。
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);
}
在 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()
使用字符串文字。明白了吗?任何问题?
最常见的是,它将作为字符串文字存储在可执行文件的只读部分中。您实际上可以通过使用-S
标志编译程序来手动验证这一点。
它将生成一个名为的程序集可执行文件name_of_your_app.s
,您可以在其中找到字符串文字(它将位于所谓的数据段中)。
有时,编译器可以放入代码段,或者根据优化级别,它会简单地将其优化掉(最容易通过创建一个不在任何地方使用的字符串文字然后使用-O3
GCC 上的标志进行编译来检查)。
这是一个(人为的)示例:
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
$
看起来这个答案解决了同样的问题。