C字符串声明

时间:2013-01-22 20:14:02

标签: c string

我对C字符串声明中的一些基础知识感到困惑。我尝试了以下代码,我发现了一些不同之处:

char* foo(){
    char* str1="string";
    char str2[7]="string";
    char* str3=(char)malloc(sizeof(char)*7);
    return str1;
    /* OR: return str2; */
    /* OR: return str3; */
    }
void main()  {
    printf("%s",foo());
    return 0;
    }

我让foo()一次返回一个str1 / 2/3,并尝试在main中打印结果。 str2返回了一些奇怪的东西,但是str1和str3返回了实际的“字符串”。

1.现在,三个声明之间的区别是什么?我认为str2不起作用的原因是因为它被声明为局部变量,这是正确的吗?

2.那么str1怎么样?如果结果在foo()结束后仍然存在,那不会导致内存泄漏吗?

3.我只是想编写一个在C中返回一个字符串的函数,并将该函数返回的值用于其他东西,我应该使用上面的str声明吗?

提前致谢!

3 个答案:

答案 0 :(得分:9)

char* str1="string";

这使str1成为指针;它指向字符串文字的第一个字符。您应该将其定义为const,因为您不允许修改字符串文字:

const char *str1 = "string";

...

char str2[7]="string";

这使str2成为char(不是指针)的数组,并将字符串文字的内容复制到其中。没有必要将其定义为const;数组本身是可写的。您也可以省略大小,并由初始化程序确定:

char str2[] = "string";

然后sizeof str2 == 7"string"为6个字节,终止'\0'为1个。)

此:

char* str3=(char)malloc(sizeof(char)*7);

写得不正确,它甚至不应该编译;至少,您应该收到编译器的警告。您正在将malloc()的结果投射到char类型。您应该将其转换为char*

char *str3 = (char*)malloc(sizeof(char) * 7);

但演员阵容是不必要的,在某些情况下可以掩盖错误;请参阅问题7.7并在comp.lang.c FAQ中跟随:

char *str3 = malloc(sizeof(char) * 7);

但是sizeof(char)根据定义是1,所以你可以写:

char *str3 = malloc(7);

malloc()分配内存,但它没有初始化它,所以如果你试图打印str3指向的字符串,你会得到垃圾 - 甚至是如果分配的空间不包含终止空字符'\0',则运行时崩溃。您可以使用strcpy()对其进行初始化,例如:

char *str3 = malloc(7);
if (str3 == NULL) {
    fprintf(stderr, "malloc failed\n");
    exit(EXIT_FAILURE);
}
strcpy(str3, "string");

您必须非常小心,您复制的数据不会超过分配的空间。 (不,`strncpy() is not the answer to this problem。)

void main()不正确;它应该是int main(void)。如果您的教科书告诉您使用void main()找到更好的教科书;它的作者不太了解C.

对于您正在使用的任何库函数,您需要适当的#include指令:<stdio.h> printf()<stdlib.h> exit()和{malloc() 1}}和<string.h> strcpy()。每个函数的文档应告诉您要包​​含哪个标题。

我知道要吸收很多东西;不要期望马上理解它。

我提到comp.lang.c FAQ;它是一个很好的资源,特别是第6节,它讨论了数组和指针以及它们之间经常令人困惑的关系。

至于你的问题3,如何从C函数返回一个字符串,由于C进行内存分配的方式(实际上它留给自己管理),结果出乎意料地复杂得多。您无法安全地返回指向局部变量的指针,因为当函数返回时变量不再存在,使调用者留下悬空指针,因此返回str2是危险的。返回字符串文字是可以的,因为它对应于整个程序执行时存在的匿名数组。您可以使用static声明一个数组并返回指向它的指针,或者您可以使用malloc()(这是最灵活的方法,但这意味着调用者需要free()内存) ,或者您可以要求调用者将指针传递给您的函数将复制结果的缓冲区。

某些语言允许您构建字符串值并简单地从函数返回它。 C,正如您现在发现的那样,不是其中一种语言。

答案 1 :(得分:6)

char* str1="string";

这将创建一个指向文字字符串的指针,该字符串将位于.data.text段上,并且始终可以访问。每当你做这样的事情时,一定要声明它const,因为如果你试图修改它,可能会发生令人讨厌的事情。

char str2[7]="string";

这将在堆栈上创建一个本地缓冲区,其中包含文字字符串的副本。一旦函数返回它就变得不可用。这解释了你得到的奇怪结果。

char* str3=(char)malloc(sizeof(char)*7);

这将在堆上创建一个缓冲区(未初始化),直到您释放它为止。你必须释放它,否则你会得到内存泄漏。

答案 2 :(得分:0)

字符串文字 "string"存储为具有静态范围的char的7元素数组,这意味着它的内存在程序启动时分配并保持到程序终止。

声明

char *str1 = "string";

将字符串文字的地址分配给str1。即使变量str1在函数退出时不再存在,其(文字"string"的地址)在函数外部仍然有效。

声明

char str2[7] = "string";

str2声明为char的数组,并将字符串文字的内容复制到其中。当函数退出时,str2不再存在,其内容不再有意义。

声明

char *str3 = (char*) malloc(sizeof(char) * 7);

可以简化为

char *str3 = malloc(sizeof *str3 * 7);

分配一个未初始化的7字节内存块,并将其地址复制到str3。当函数退出时,变量str3不再存在,但它指向的内存仍然被分配。如上所述,此内存泄漏,因为您不会在调用代码中保留指针的值。请注意,由于您没有将任何内容复制到此块,main中的输出将是随机的。

此外,除非您的编译器文档明确列出void main()作为main函数的合法签名,否则请改用int main(void)