簡體   English   中英

struct-> char_member =“”和strcat(struct-> char_member,“string”)之間有什么區別?

[英]what's difference between struct->char_member = “” and strcat(struct->char_member,“string”)?

我有以下代碼:

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

struct test {
    char *str;
};

int main(void)
{
    struct test *p = malloc(sizeof(struct test));
    p->str = "hello world";
    printf("%s\n",p->str);
    return 0;
}

它工作正常。 但是當我寫這樣的時候:

struct test *p = malloc(sizeof(struct test));
p->str="hello";
strcat(p->str," world");

或這個:

struct test *p = malloc(sizeof(struct test));
strcat(p->str,"hello world");

我遇到了分段錯誤。

我在這里找到了一些相關的解釋:

您只為結構本身分配內存。 這包括指向char的指針,它在32位系統上只有4個字節,因為它是結構的一部分。 它不包含未知長度的字符串的內存,所以如果你想要一個字符串,你必須手動為它分配內存

使用C中的字符指針為結構分配內存

有了解釋,我知道如果我想使用strcat,正確的代碼應該是這樣的:

struct test *p = malloc(sizeof(struct test));
p->str = malloc(size);
strcat(p->str,"hello world");

所以我的問題是為什么p-> str =“hello world”不需要分配內存但strcat(p-> str,“hello world”)需要在使用前分配內存?

我的編譯器是“gcc(Debian 4.9.2-10)4.9.2”。 我的英語非常基礎,請不要介意:)

需要明確的是,分配到p->str並不需要分配。 p->str只是一個內存地址,你可以放入任何內存地址,有效與否。 當您想要操作內存地址的內容時,需要分配。

p->str = "hello world"的情況下,編譯器提前保留一個內存區域並在其中放入“hello world”字符串,並使用該地址。

注意strcat的第二個參數也是字符串文字,並且不需要分配它。

在第一個示例中,您將一個不可變字符串分配給p->str (它存儲在只讀存儲器中)。 因此,嘗試更改內存會導致seg-fault。

在第二個示例中,您未能使用mallocp->str分配空間。 由於p未初始化,因此您正在讀取您不擁有的內存中的某個隨機位置。

嘗試:

struct test *p = malloc(sizeof(struct test));
p->str=(char *)malloc(12 * sizeof(char));
strcpy(p->str, "hello");
strcat(p->str," world");

這里我們有malloc足夠的空間用於“hello world”(加上'\\ 0'字符)。 strcpy將字符串“hello”復制到已分配的內存中的位置。 現在strcat成功了,因為你“擁有”p-> str指向的內存。

另外不要忘記你有malloc的free()內存!

編輯:作為旁注,我認為你可能會對為結構分配內存感到困惑。 在這種情況下,為struct分配內存只能為char *提供足夠的內存; 但是你沒有為指向的實際指針分配內存。

實際上沒有必要為struct test分配內存,只能為char *分配內存。 更好的是:

struct test p;
p.str=(char *)malloc(12 * sizeof(char));
strcpy(p.str, "hello");
strcat(p.str," world");

"hello, world""hello"" world"都是字符串文字 ; 它們都存儲為char數組,以便程序一啟動就可以使用,並且在程序的生命周期內可見。

該聲明

p->str = "hello, world";

將字符串文字的地址復制到p->str 這適用於printf語句以及只需要讀取字符串的任何其他內容。 但是,在聲明中

p->str = "hello";
strcat( p->str, " world" );

您試圖通過將字符串" world"附加到它來修改字符串文字"hello" 字符串文字是不可修改的,並且嘗試這樣做會導致未定義的行為 ,在您的情況下是段錯誤 - 在許多流行的桌面平台上,字符串文字保存在內存的只讀部分。

因此,您需要留出可以寫入的內存區域。 您可以使用動態執行此操作

p->str = malloc( SOME_SIZE);  // enough space to store your final string
strcpy( p->str, "hello" );  // copy the contents of "hello" to the memory str points to
strcat( p->str, " world" ); // append the contents of " world" to the memory str points to

或者你可以設置p->str指向你在別處聲明的數組

char buffer[SOME_SIZE];
p->str = buffer; // assigns the *address* of buffer to p->str

或者您可以在struct定義中將str聲明為char 數組

struct test
{
  char str[SOME_SIZE];
};

其中SOME_SIZE足以容納您想要存儲的任何字符串。 請注意,在這種情況下, p->str = "hello" 不起作用; 你不能使用=運算符來相互分配數組的內容; 在這種情況下你必須使用strcpy

顯然,使用malloccalloc動態分配更加靈活; 您可以根據需要分配盡可能多的內存,並且可以根據需要使用realloc增大或縮小動態緩沖區您只需要記住在完成后釋放p->str

您仍然可以將字符串文字的地址分配給p->str ,只需要知道您不能將該地址傳遞給strcpystrcatstrtok等函數或任何其他嘗試修改輸入字符串內容的函數。

你是對的。 但是你應該在這里使用strcpy而不是strcat ,因為strcat會將一個字符串附加到p->str ,這是未初始化的。

事實上p->str = "hello world"; 將使p->str指向(匿名)字符串litteral。 它的存儲器通常在程序執行開始時自動分配。

暫無
暫無

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

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