C中的字符串参数是否动态分配?

时间:2013-07-02 03:28:34

标签: c string

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

void example(char* str)

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

example("testing");

“测试”的值是否在堆上动态分配,所以在能够调用“示例”的函数的范围被破坏(并且需要稍后释放)后,我将能够使用它,或者是它是堆栈上的局部变量,所以我需要使用malloc创建一个新的字符串并将值存储在那里,如果我希望它继续存在,比如一个hashmap?

感谢。

3 个答案:

答案 0 :(得分:8)

当您在程序中编写"testing"时,它将被编译为字符串文字,并且在编译期间将分配它的空间。当你得到一个指向它的指针时,它是指向内存中该位置的指针。您无需使用malloc()进行分配,也不应free()分配#include <stdio.h> int main() { char *a = "abc\n"; a[0]='X'; printf(a); return(0); } 。但是尝试修改其内容也不是一个好主意,因为编译器可能会将它放在只读区域(也就是说,它被编译为常量) - 例如,以下程序在我的Linux桌面上崩溃:

{{1}}

答案 1 :(得分: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"))不能保证是不同的指针,也不能保证它们是相同的指针值。 / LI>
  • 您绝不能free()字符串文字。
  • 您绝不能写字符串文字。
  • 字符串文字将在程序的整个生命周期内保持可用,因此它可以正常工作,例如哈希键。

知道了吗?有问题吗?

答案 2 :(得分:1)

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

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

有时编译器可以放入代码段或根据优化级别将其简单地优化(最容易通过创建一个未在任何地方使用的字符串文字来检查,然后使用-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
$

看起来this answer解决了同样的问题。