簡體   English   中英

使用“=”分配帶有char數組的struct?

[英]assign struct with char array inside using “=” works?

我正在審查某人的代碼,開發人員已將一個結構分配給另一個。 該struct包含一個char數組。 不知何故,“工作”,意味着結構A中的char數組確實被復制到結構B(而不是通過引用)。 我完全不知所措。 可以這樣向我解釋一下嗎? 我寫了一個小程序來說明“問題”。

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

/**************************************
 * some define and typedef for later
 **************************************/
#define MAX_LEN (80)

typedef struct month_s
{
    char name[MAX_LEN];
} month_st;

/**************************************
 * This bit is clear.
 **************************************/
static void usingString()
{
    char mCur[MAX_LEN] = {"Jan"};
    char mNext[MAX_LEN] = {"Feb"};

    /** this doesn't compile (of course) */
    //mCur = mNext;

    /** we need a pointer/reference */
    char *pmCur = &mCur[0];

    /** however now we "copy by reference"...*/
    pmCur = &(mNext[0]);

    /** ...so this change also applies to pmCur*/
    strcpy(mNext, "Mar");

    /** ...so pmCur is now "Mar"*/
    printf("%s: %s\n", __func__, pmCur);
}

/**************************************
 * I though the same/s.th. similar
 * as above happens here. But this "works".
 * I'm surprised to see that not to be
 * the case. Can someone explain?
 **************************************/
static void usingStruct()
{
    month_st mCur = {"Jan"};
    month_st mNext = {"Feb"};

    /** I would have thought this is "copy by reference" for the string! */
    mCur = mNext;

    /** I would have thought this also overrides mCur.name
            'cause it's pointing to mNext.name now */
    strcpy(mNext.name, "Mar");

    /** how come this works??? mCur.name is still "Feb"*/
    printf("%s: %s\n", __func__, mCur.name);
}
/**************************************
 * just the main()
 **************************************/
int main()
{
    usingString();
    usingStruct();
    return 0;
}

你可能最驚訝的是數組和指針在C中是不一樣的。在你的例子中的數組成員不僅包含指向字符串的指針而且包含字符串本身。 因此,當您將一個struct實例分配給另一個struct實例時,將復制所有這些。

我看到有關指針和數組之間差異的三種解釋,但它們似乎並沒有解決被問到的問題,正如我所理解的那樣。

正如我所理解的那樣,問題是:“我知道我不能將一個數組分配給另一個,所以如果數組在一個結構中,為什么還能這樣做?”

答案基本上是“因為語言這么說”。 盡管結構是一種聚合類型,並且很可能包含一個數組,但語言規范說結構是可分配的,因此結構是可分配的。 這是第6.5.16.1 Simple assignmentN1256N1570中的 6.5.16.1 Simple assignment

(在引擎蓋下,編譯器可能必須實現內存復制,但這是編譯器的問題,而不是你的問題。)

根據你的結構聲明:

typedef struct month_s
{
    char name[MAX_LEN];
} month_st;

sizeof(month_st)包括作為結構成員的char數組的空格。(注意你正在進行靜態內存分配, name不是指針而是數組)。
因此,當您將一個strct變量分配給其他變量時,它將完全復制數組(或者我們可以說總sizeof(month_st))將被復制)。

接下來,您將聲明兩個結構變量:

month_st mCur = {"Jan"};
month_st mNext = {"Feb"}; 

變量mCurmNext是不同的。 當你做任務時nCur = mNext; mNext值復制到nCur結構變量的內存,但兩者都有獨立的(自己的)內存。

strcpy()語句:

strcpy(mNext, "Mar");

僅影響變量mNext ,它不會改變變量nCur內容。

為了您的困惑,假設您已經按如下方式聲明了結構:

typedef struct month_s
{
    char* name;
} month_st; 

還是做nCur = mNext; 你將sizeof(month_st))字節從mNextnCur變量,因此只復制地址,因為name是一個指向內存的指針。

在這種情況下,完整的數組/內存(您可能動態分配)不復制它稱為淺復制

你很困惑,因為你認為mCurmNext是指向對象的指針,而實際上它們是對象。 struct month_s僅在內存中分配空間以存儲月份名稱。 它沒有為存儲指向任何東西的指針分配內存。 因此,當mCur被分配的值mNext ,整個對象,因為它是由值拷貝而不是通過參考復制。

為方便起見,我注釋了您的代碼:

static void usingStruct()
{
    month_st mCur = {"Jan"};
    month_st mNext = {"Feb"};

    /** mCur and mNext are both objects. Assigning one to the other 
      * will copy by value and not by reference (as there is no reference
      * to be copied in the first place). After this assignment, 
      * mCur == {"Feb"}  */
    mCur = mNext;

    /** mNext.name is the address of the memory allocated to the object
      * mNext. This line copies the characters "Mar" to the first three
      * bytes of this memory allocation */
    strcpy(mNext.name, "Mar");

    /** At this point, mCur == {"Feb"} and mNext == {"Mar"} */
    printf("%s: %s\n", __func__, mCur.name);
}

暫無
暫無

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

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