繁体   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