C语言 使用 malloc 分配字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41830461/
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 10:34:35  来源:igfitidea点击:

Allocating string with malloc

cstringmalloc

提问by FranzGoogle

I'm new in programming in C and now I'm studying strings. My question is: if I allocate a string using malloc(as in the code below), is the NULL character automatically inserted at the end of the string? I find an answer in another question here, and it seems that the NULL character is not automatically included. But here comes the problem: I know functions like strlendon't work if there isn't the NULL character, and in this code I use it and it works. So I think there is \0at the end of my string, even if I don't write it anywhere. What's the answer?

我是 C 编程的新手,现在我正在学习字符串。我的问题是:如果我使用malloc(如下面的代码)分配一个字符串,NULL 字符是否会自动插入到字符串的末尾?我在这里的另一个问题中找到了答案,似乎没有自动包含 NULL 字符。但问题来了:我知道strlen如果没有 NULL 字符,这样的函数就不起作用,在这段代码中,我使用它并且它起作用了。所以我认为\0在我的字符串末尾有,即使我没有在任何地方写它。答案是什么?

Here's the code:

这是代码:

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

int main(int argc, char** argv) {
    char *stringa1;
    int n;
    int i;

    printf("How many characters in the string? ");
    scanf("%d", &n);

    stringa1 = (char*) malloc(n*sizeof(char));

    printf("Insert the string: ");
    scanf("%s", stringa1);

    free(stringa1);

    return 0;
}

回答by RoadRunner - MSFT

malloc()returns a void*pointer to a block of memory stored in the heap. Allocating with malloc()does not initialize any string, only space waiting to be occupied.To add a null-terminating character, you either have to do this yourself, or use a function like scanf(), which adds this character for you. Having said this, you need to allocate space for this \0character beforehand.

malloc()返回void*指向存储在堆中的内存块的指针。分配 withmalloc()不会初始化任何字符串,只会初始化等待被占用的空间。要添加空终止字符,您要么必须自己执行此操作,要么使用类似 的函数scanf(),它会为您添加此字符。话虽如此,您需要\0事先为该字符分配空间。

Your malloc()call should be this instead:

你的malloc()电话应该是这样的:

stringa1 = (char*) malloc((n+1)*sizeof(char)); /*+1 for '
if (stringa1 == NULL) {
    /* handle exit */
' character */

Note:You don't need to cast return of malloc. For more information, read this.

注意:您不需要强制转换 malloc 的返回值。有关更多信息,请阅读

Another thing to point out is sizeof(char)is 1, so multiplying this in your malloc()call is not necessary.

另一件事要指出的sizeof(char)1,因此在您的malloc()通话中乘以它是没有必要的。

You also need to check if malloc()returns NULL. This can be done like this:

您还需要检查是否malloc()返回NULL。这可以像这样完成:

if (scanf("%d", &n) != 1) {
    /* handle exit */

Also, you can only use strlen()on a null-terminated string, otherwise this ends up being undefined behaviour.

此外,您只能strlen()在以空字符结尾的字符串上使用,否则这最终会成为未定义的行为

Once scanf()is called, and the stringa1contains some characters, you can call strlen()on it.

一旦scanf()被调用,并且stringa1包含一些字符,你可以调用strlen()它。

Additionally, checking return of scanf()is also a good idea. You can check it like this:

此外,检查 return ofscanf()也是一个好主意。你可以这样检查:

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

int main(void) {
    char *stringa1 = NULL;
    size_t n, slen;

    printf("How many characters in the string? ");
    if (scanf("%zu", &n) != 1) {
        printf("Invalid input\n");
        exit(EXIT_FAILURE);
    }

    stringa1 = malloc(n+1);
    if (stringa1 == NULL) {
        printf("Cannot allocate %zu bytes for string\n", n+1);
        exit(EXIT_FAILURE);
    }

    printf("Insert the string: ");
    scanf("%s", stringa1);

    slen = strlen(stringa1);
    printf("String: %s Length: %zu\n", stringa1, slen);

    free(stringa1);
    stringa1 = NULL;

    return 0;
}

Your code with these changes:

您的代码进行了这些更改:

printf("How many characters in the string? ");

回答by P.P

if I allocate a string using malloc (as in the code below), is the NULL character automatically inserted at the end of the string?

如果我使用 malloc 分配一个字符串(如下面的代码所示),NULL 字符是否会自动插入到字符串的末尾?

No. malloc()returns a block of uninitialized memory.

否。malloc()返回一块未初始化的内存。

I know functions like 'strlen' don't work if there isn't the NULL character, and in this code I use it and it works. So I think there is '\0' at the end of my string, even if I don't wrote it nowhere.

我知道如果没有 NULL 字符,像 'strlen' 这样的函数就不起作用,在这段代码中,我使用了它并且它起作用了。所以我认为我的字符串末尾有 '\0' ,即使我没有在任何地方写它。

scanf()inserts the null byte ('\0') for you when you use %sformat specifier (assuming scanf()succeeded).

scanf()'\0'当您使用%s格式说明符(假设scanf()成功)时,为您插入空字节 ( )。

From man scanf():

来自man scanf()

s Matches a sequence of non-white-space characters; the next pointer must be a pointer to the initial element of a character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically.The input string stops at white space or at the maximum field width, whichever occurs first.

s 匹配非空白字符序列;next 指针必须是指向字符数组的初始元素的指针,该元素的长度足以容纳输入序列和自动添加的终止空字节 ('\0')。输入字符串在空白处或最大字段宽度处停止,以先发生者为准。

(emphasis mine).

(强调我的)。

By the way, you should do error checking for scanf()and malloc()calls.

顺便说一句,您应该对scanf()malloc()调用进行错误检查。

回答by Paul Ogilvie

The definition of "string" in C is a sequence of characters, terminated by a null character.

C 中“字符串”的定义是一个字符序列,以空字符结尾

To allocate memory for a string, count the chracters (e.g. strlen) and add 1 for this terminating null character.

要为字符串分配内存,请计算字符数(例如strlen)并为此终止空字符加 1。

Functions like scanfand strcpyadd the null character; a function like strncpydoesn't always do that.

类似scanfstrcpy添加空字符的函数;像strncpy这样的功能并不总是这样做。

回答by Vlad from Moscow

mallocreturns pointer to an uninitialized memory extent.

malloc返回指向未初始化内存范围的指针。

If you want that the memory extent would be initialized by zeroes then you can use another standard function callocinstead of malloc.

如果您希望内存范围由零初始化,那么您可以使用另一个标准函数calloc而不是malloc.

Take into account that usually such a question like this

考虑到通常这样的问题

stringa1 = ( char* )malloc( ( n + 1 ) *sizeof( char ) );

imply that the terminating zero is not counted. So you have to allocate one more byte of memory. For example

意味着不计算终止零。所以你必须再分配一个字节的内存。例如

stringa1 = ( char* )calloc( n + 1, sizeof( char ) );

or

或者

scanf("%s", stringa1);

In the last case you may apply the function strlenwhich returns 0 because the memory extent is zero-initialized.

在最后一种情况下,您可以应用strlen返回 0的函数,因为内存范围是零初始化的。

This call of scanf

这个电话 scanf

fgets( stringa1, n + 1, stdin );

is unsafe. It is better to use fgetsinstead. For example

是不安全的。最好fgets改用。例如

stringa1[strcspn( stringa1, "\n" )] = '##代码##';

This function can append the string with the new line character. To remove it from the string you can write

这个函数可以用换行符追加字符串。要将其从字符串中删除,您可以编写

##代码##