簡體   English   中英

關於動態分配內存到char指針的簡單問題

[英]Simple question on dynamically allocating memory to a char pointer

我正在攻讀數據結構和算法考試。 與動態內存分配相關的示例問題之一要求您創建一個傳遞字符串的函數,該函數將其復制到用戶定義的char指針。 這個問題提供了結構體開始。 我做了這樣的事情:

typedef struct smart_string {
    char *word;
    int length;
} smart_string;

smart_string* create_smart_string(char *str)
{
    smart_string *s = (smart_string*)malloc(sizeof(smart_string));
    s->length = strlen(str);
    s->word = malloc(s->length);
    strcpy(s->word, str);
    return s;
}

但答案是這樣的

typedef struct smart_string {
    char *word;
    int length;
} smart_string;

smart_string *create_smart_string(char *str)
{
    smart_string *s = malloc(sizeof(smart_string));
    s->length = strlen(str);
    s->word = malloc(sizeof(char) * (s->length + 1));
    strcpy(s->word, str);
    return s;
}

我繼續使用代碼:塊並測試它們以查看任何重大差異。 據我所知,他們的輸出是一樣的。

我按照它的方式完成了我的代碼,因為我想如果我們要為s->word分配一個特定的內存塊,那么它應該是與s ->length相同的字節數,因為那是我們要復制的字符串。

但是,下面的正確答案sizeof(char) (只有1個字節)與s->length + 1相乘。 為什么需要加1s->length s->length乘以sizeof(char)的重要性是什么? 我在答案中犯了什么錯誤,我應該注意什么?

您的答案不正確,因為它沒有考慮終止'\\0'字符。 在C中,字符串以0結尾。 這就是他們的長度可以確定的方式。 strlen()典型實現看起來像

size_t strlen(char const *str)
{
    for (char const *p = str; *p; ++p);  // as long as p doesn't point to 0 increment p
    return p - str;  // the length of the string is determined by the distance of
}                    // the '\0'-character to the beginning of the string.

但是,這兩種“解決方案”都是愚蠢的。 為什么要在免費商店(“堆”)上分配一個由int和指針組成的結構!? smart_string::length是一個int是另一個wtf。

#include <stddef.h>  // size_t

typedef struct smart_string_tag {  // *)
    char *word;
    size_t length;
} smart_string_t;

#include <assert.h>  // assert()
#include <string.h>  // strlen(), strcpy()
#include <stdlib.h>  // malloc()

smart_string_t create_smart_string(char const *str)
{
    assert(str);  // make sure str isn't NULL

    smart_string_t new_smart_string;
    new_smart_string.length = strlen(str);
    new_smart_string.word = calloc(new_smart_string.length + 1, sizeof *new_smart_string.word);

    if(!new_smart_string.word) {
        new_smart_string.length = 0;
        return new_smart_string;
    }

    strcpy(new_smart_string.word, str);
    return new_smart_string;
}

*) 了解C命名空間

sizeof(char) == 1根據定義,所以無關緊要。

你不應該轉換malloc的結果: 我是否轉換了malloc的結果?

而你唯一的真正區別是strlen返回字符串的長度,不包括終止的NUL( '\\0' )字符,所以你需要在解決方案中添加+ 1到緩沖區的大小。

如果你在那里復制字符串,終止字符將不會被復制(或者更糟糕的是,它將被復制到其他內存中),因此,任何處理字符串的函數(除非你使用特殊的安全函數,如strscpy )將通過緩沖區並通過它,因為它們不會找到結束。 在這一點上,它是未定義的行為,一切都可能發生,即使按預期工作,但不能依賴於此。

它按預期工作的原因是因為緩沖區旁邊的內存可能是0,因此它被解釋為終止字符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM