使用“=”在内部分配带有char数组的结构?

Posted

技术标签:

【中文标题】使用“=”在内部分配带有char数组的结构?【英文标题】:assign struct with char array inside using "=" works? 【发布时间】:2013-07-27 16:27:49 【问题描述】:

我正在审查某人的代码,而开发人员已将一个结构分配给另一个结构。该结构包含一个 char 数组。不知何故,“工作”,这意味着来自 struct A 的 char 数组确实被复制到 struct 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;

【问题讨论】:

【参考方案1】:

我看到了关于指针和数组之间区别的三种解释,但据我所知,它们似乎没有解决所提出的问题。

据我所知,问题是:“我知道我不能将一个数组分配给另一个数组,那么为什么 可以 如果数组在结构中,我可以这样做?”

答案基本上是“因为语言是这样说的”。尽管结构是聚合类型,并且很可能包含数组,但语言规范说结构是可分配的,因此结构是可分配的。这是N1256 和N1570 中的6.5.16.1 Simple assignment 部分。

(在后台,编译器可能必须实现内存副本,但这是编译器的问题,而不是你的问题。)

【讨论】:

【参考方案2】:

您可能最惊讶的是,数组和指针在 C 中不是一回事。在您的示例中,数组成员不仅包含指向字符串的指针,还包含字符串本身。因此,当您将一个 struct 实例分配给另一个实例时,所有这些都会被复制。

【讨论】:

【参考方案3】:

根据你的结构声明:

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)) 字节从mNext 复制到nCur 变量,因此只有复制为name 的地址是指向内存的指针。

在这种情况下,完整的数组/内存(您可能会动态分配)不复制这称为浅复制

【讨论】:

没有Shadow CopyShallow Copy【参考方案4】:

您很困惑,因为您认为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);

【讨论】:

以上是关于使用“=”在内部分配带有char数组的结构?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Hibernate 在内部保存带有集合的实体?

在内部使用带有 UIWebView 的 url 方案来更改 UILabel

在内部函数内部分配外部变量的python闭包

python Python并行分配。交换如何在内部工作

当结构在内部向量中包含各种数量的元素时,如何应用面向数据的设计?

如何使用 vueJS 在内部数组中显示 JSON 数据?