重新分配字符串文字

时间:2015-07-29 17:43:46

标签: c string pointers

这是一个非常基本的问题,但我没有找到明确的答案。我试着理解C中的字符串文字是如何工作的。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
        char *str = "Hello World!";
        str = "Reassign str.";

        char *str2 = "Something.";

        str = strdup(str2);

        free(str);

        exit(EXIT_SUCCESS);
}

当我对字符串文字str = "Reassign str."str = strdup(str2)执行Hello World字符串时会发生什么?它是可执行文件的一部分,它是否超出范围,重新分配str后是否释放了内存?

7 个答案:

答案 0 :(得分:4)

字符串文字具有静态存储持续时间。在程序执行期间,它们不会被销毁并具有相同的地址。

在这些陈述中

    str = "Reassign str.";
    //...
    str = strdup(str2);

指针str只是由其他一些地址重新分配。在第一个语句中,它获取字符串文字“重新分配str”的第一个字符的地址。在第二个语句中,它获取包含str2指向的字符串文字副本的字符数组的动态分配内存的地址。

根据C标准(6.4.5字符串文字)

  

6在转换阶段7中,附加一个值为零的字节或代码   每个由字符串文字产生的多字节字符序列   或者文字.78)然后使用多字节字符序列   初始化一组静态存储持续时间和长度   足以包含序列。对于字符串文字,   数组元素具有char类型,并使用个体初始化   多字节字符序列的字节。

和(6.2.4对象的存储持续时间)

  

3对象...具有静态存储持续时间。 它的一生就是   程序的整个执行及其存储的值被初始化   程序启动前只有一次

至于字符串文字本身,你可能不会改变它们。任何更改字符串文字的尝试都会导致程序的未定义行为。

来自C标准(6.4.5字符串文字)

  

7未指明这些阵列是否与它们不同   元素具有适当的值。 如果程序尝试   修改这样的数组,行为是未定义的。

例如,您可能不会写

    char *str = "Hello World!";
    *str = 'h';

答案 1 :(得分:2)

当你这样做时

char *str = "Hello World!";  

编译器为该字符串文字留出了字节strlen(str) + 1的内存。当指针str被重新分配时,为字符串文字"Hello World!"分配的内存不会被销毁/释放,而是在其范围内持续存在。

答案 2 :(得分:2)

代码中的一切都正常。

    char *str = "Hello World!"; 

好的,你声明一个char *指向一个字符串文字。为了正确,你应该写const char *str =,因为字符串litteral是一个不可修改的字符串(str[4] = 'u';是不正确的)

    str = "Reassign str.";

好吧指针str现在指向另一个字符串。与上述相同,它应该仍然是常量。

    char *str2 = "Something.";

仍然是同一个故事

    str = strdup(str2);

现在str指向malloc的字符串。这是第一次str不是const是正确的。 str[0] = 's';在这里是正确的。

    free(str);

好的,你释放strdup分配的字符串。

    exit(EXIT_SUCCESS);

您很好地将定义的值(0)返回给环境。

答案 3 :(得分:2)

好像还没有足够的答案,但我认为还有一个方面值得一提:

是的,代码中的字符串文字具有静态存储是正确的,因此在整个程序执行期间它将是 alive 。在这方面,没有任何东西可以发生(你甚至无法改变它)。从技术上讲,这通常意味着字符串是程序的 part 并放入只读的数据段。

但是,在您的情况下,优化编译器将检测到"Hello World!"从未实际使用过,因此它将从已编译的程序中消失。这对优化工具来说是合法的,因为它不会改变程序的可观察行为

> gcc -ostrlit strlit.c
> strings strlit | grep Hello
Hello World!
> gcc -O3 -ostrlit strlit.c
> strings strlit | grep Hello
>

答案 4 :(得分:1)

通常,静态字符串位于静态数据部分中。在这种情况下,因为你的程序没有做任何事情,我不太确定;可以优化所有静态字符串。

在实际程序中,您实际使用这些静态字符串,它们将具有固定的地址。

绝不会str = strdup(str2);释放任何记忆。在C中,内存永远不会自行释放。

答案 5 :(得分:1)

让我们打破这个:

char *str = "Hello World!";

声明一个名为str

指向char 的指针
char *str

声明字符串文字

            "Hello World!";

str设置为指向文字的第一个字符。

文字具有静态存储持续时间 - 它被编译到您的可执行文件中,始终存在,并且无法移动或更改。

指针只是一个指针,你可以随时指向其他东西。

答案 6 :(得分:0)

声明字符串文字时,例如:

char *str = "Hello World!";

"Hello World!"字符串存储在内存的只读部分。所以如果你是其中之一:

str[1] = 'i';
strcpy(str, "Goodbye!");

你很可能是核心转储。另一方面,如果你这样做:

str = malloc(10);
strcpy(str, "Goodbye!");

你会没事的,虽然你会松开你对原始字符串的指针。