C语言 C 字符串声明

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14467200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:07:11  来源:igfitidea点击:

C string declaration

cstring

提问by turtlesoup

I am confused about some basics in C string declaration. I tried out the following code and I noticed some difference:

我对 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;
    }

I made foo() return str1/2/3 one at a time, and tried to print the result in the main. str2 returned something weird, but str1 and str3 returned the actual "string".

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

1.Now, what's the difference between the three declarations? I think the reason why str2 didn't work is because it is declared as a local variable, is that correct?

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

2.Then what about str1? If the result remains after the foo() ended, wouldn't that cause memory leak?

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

3.I'm simply trying to write a function that returns a string in C, and use the value returned by that function for other stuff, which str declaration above should I use?

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

Thanks in advance!

提前致谢!

回答by Keith Thompson

char* str1="string";

This makes str1a pointer; it points to the first character of the string literal. You should define it as const, because you're not allowed to modify a string literal:

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

const char *str1 = "string";

...

...

char str2[7]="string";

This makes str2an array of char(not a pointer), and copies the contents of the string literal into it. There's no need to define it as const; the array itself is writable. You can also omit the size and let it be determined by the initializer:

这会生成str2一个char(不是指针)的数组,并将字符串文字的内容复制到其中。无需将其定义为const; 数组本身是可写的。你也可以省略大小,让它由初始值设定项决定:

char str2[] = "string";

Then sizeof str2 == 7(6 bytes for "string"plus 1 for the terminating '\0').

然后sizeof str2 == 7(6 个字节"string"加上 1 表示终止'\0')。

This:

这个:

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

is written incorrectly, and it shouldn't even compile; at the very least, you should have gotten a warning from your compiler. You're casting the result of malloc()to type char. You should be converting it to char*:

写错了,它甚至不应该编译;至少,你应该从你的编译器那里得到警告。您正在将 的结果转换malloc()为 type char。您应该将其转换为char*

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

But the cast is unnecessary, and can mask errors in some cases; see question 7.7 and following in the comp.lang.c FAQ:

但是强制转换是不必要的,并且在某些情况下可以掩盖错误;请参阅comp.lang.c FAQ中的问题 7.7 及以下内容:

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

But sizeof(char)is 1 by definition, so you can just write:

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

char *str3 = malloc(7);

malloc()allocates memory, but it doesn't initialize it, so if you try to print the string that str3points to, you'll get garbage -- or even a run-time crash if the allocated space doesn't happen to contain a terminating null character '\0'. You can initialize it with strcpy(), for example:

malloc()分配内存,但它不会初始化它,所以如果你尝试打印str3指向的字符串,你会得到垃圾——如果分配的空间没有碰巧包含终止空值,甚至会导致运行时崩溃性格'\0'。您可以使用 初始化它strcpy(),例如:

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

You have to be very careful that the data you're copying is no bigger than the allocated space. (No, `strncpy() is not the answer to this problem.)

您必须非常小心,您正在复制的数据不能大于分配的空间。(不,`strncpy() 不是这个问题的答案。)

void main()is incorrect; it should be int main(void). If your textbook told you to use void main()find a better textbook; its author doesn't know C very well.

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

And you need appropriate #includedirectives for any library functions you're using: <stdio.h>for printf(), <stdlib.h>for exit()and malloc(), and <string.h>for strcpy(). The documentation for each function should tell you which header to include.

并且您需要#include为您正在使用的任何库函数提供适当的指令:<stdio.h>for printf()<stdlib.h>forexit()malloc()<string.h>for strcpy()。每个函数的文档都应该告诉您要包​​含哪个标头。

I know this is a lot to absorb; don't expect to understand it all right away.

我知道这需要大量吸收;不要指望一下子就明白这一切。

I mentioned the comp.lang.c FAQ; it's an excellent resource, particularly section 6, which discusses arrays and pointers and the often confusing relationship between them.

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

As for your question 3, how to return a string from a C function, that turns out to be surprisingly complicated because of the way C does memory allocation (basically it leaves to to manage it yourself). You can't safely return a pointer to a local variable, because the variable ceases to exist when the function returns, leaving the caller with a dangling pointer, so returning your str2is dangerous. Returning a string literal is ok, since that corresponds to an anonymous array that exists for the entire execution of your program. You can declare an array with staticand return a pointer to it, or you can use malloc()(which is the most flexible approach, but it means the caller needs to free()the memory), or you can require the caller to pass in a pointer to a buffer into which your function will copy the result.

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

Some languages let you build a string value and simply return it from a function. C, as you're now discovering, is not one of those languages.

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

回答by imreal

char* str1="string";

This creates a pointer to a literal string that will be located on either .dataor .textsegments and is accessible at all times. Whenever you do something like that, be sure to declare it const, because if you try to modify it, nasty things might happen.

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

char str2[7]="string";

This creates a local buffer on the stack with a copy of the literal string. It becomes unavailable once the function returns. That explains the weird result you're getting.

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

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

This creates a buffer on the heap (uninitialized) that will be available until you free it. And free it you must, or you will get a memory leak.

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

回答by John Bode

The string literal"string"is stored as a 7-element array of charwith static extent, meaning that the memory for it is allocated at program startup and held until the program terminates.

字符串文字"string"存储为一个7个元素的数组char的静态程度,这意味着它的内存在程序启动时分配并保持,直到程序结束。

The declaration

声明

char *str1 = "string";

assigns the addressof the string literal to str1. Even though the variable str1ceases to exist when the function exits, its value(the address of the literal "string") is still valid outside of the function.

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

The declaration

声明

char str2[7] = "string";

declares str2as an array of char, and copies the contentsof the string literal to it. When the function exits, str2ceases to exist, and its contents are no longer meaningful.

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

The declaration

声明

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

which can be simplified to

可以简化为

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

allocates an uninitialized 7-byte block of memory and copies its address to str3. When the function exits, the variable str3ceases to exist, but the memory it points to is still allocated. As written, this isa memory leak, because you don't preserve the value of the pointer in the calling code. Note that, since you don't copy anything to this block, the output in mainwill be random.

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

Also, unless your compiler documentation explicitlylists void main()as a legal signature for the mainfunction, use int main(void)instead.

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