简体   繁体   English

使用“=”分配带有char数组的struct?

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

I am reviewing someone's code and the developer has assigned one struct to another. 我正在审查某人的代码,开发人员已将一个结构分配给另一个。 The struct contains a char array. 该struct包含一个char数组。 Somehow that "works", meaning the char array from struct A does get copied to struct B (not by reference). 不知何故,“工作”,意味着结构A中的char数组确实被复制到结构B(而不是通过引用)。 I'm totally baffled. 我完全不知所措。 Can so explain that to me? 可以这样向我解释一下吗? I have written up a little program to illustrate the "problem". 我写了一个小程序来说明“问题”。

#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;
}

What you are probably most astonished about is that arrays and pointers are not the same thing in C. An array member as in your example contains not only a pointer to the string but the string itself. 你可能最惊讶的是数组和指针在C中是不一样的。在你的例子中的数组成员不仅包含指向字符串的指针而且包含字符串本身。 Thus all theses are copied when you assign one struct instance to the other. 因此,当您将一个struct实例分配给另一个struct实例时,将复制所有这些。

I see three explanations about the difference between pointers and arrays, but they don't seem to address the question being asked, as I understand it. 我看到有关指针和数组之间差异的三种解释,但它们似乎并没有解决被问到的问题,正如我所理解的那样。

The question, as I understand it, is: "I know that I can't assign one array to another, so why can I do it if the array is inside a struct?" 正如我所理解的那样,问题是:“我知道我不能将一个数组分配给另一个,所以如果数组在一个结构中,为什么还能这样做?”

The answer is, basically, "because the language said so". 答案基本上是“因为语言这么说”。 Even though a struct is an aggregate type, and may very well contain an array, the language spec says that structs are assignable, and therefore structs are assignable. 尽管结构是一种聚合类型,并且很可能包含一个数组,但语言规范说结构是可分配的,因此结构是可分配的。 This is section 6.5.16.1 Simple assignment in both N1256 and N1570 . 这是第6.5.16.1 Simple assignmentN1256N1570中的 6.5.16.1 Simple assignment

(Under the hood, the compiler may have to implement a memory copy, but that's the compiler's problem, not yours.) (在引擎盖下,编译器可能必须实现内存复制,但这是编译器的问题,而不是你的问题。)

According to your declaration of struct: 根据你的结构声明:

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

sizeof(month_st) includes spaces for char array that is member of structs.(Notice you are doing static memory allocation, name is not pointer but array). sizeof(month_st)包括作为结构成员的char数组的空格。(注意你正在进行静态内存分配, name不是指针而是数组)。
So when you assign one strct variable to other variable it completely copy array(or we can say total sizeof(month_st)) bytes will be copied). 因此,当您将一个strct变量分配给其他变量时,它将完全复制数组(或者我们可以说总sizeof(month_st))将被复制)。

Next, your are declaring two struct variables: 接下来,您将声明两个结构变量:

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

Memories for both variables mCur and mNext are different. 变量mCurmNext是不同的。 When you do assignment nCur = mNext; 当你做任务时nCur = mNext; , values of mNext copies to nCur struct variable's memory but both have separate (thier-own) memory. mNext值复制到nCur结构变量的内存,但两者都有独立的(自己的)内存。

strcpy() statement: strcpy()语句:

strcpy(mNext, "Mar");

effecting only variable mNext , it don't change content of variable nCur . 仅影响变量mNext ,它不会改变变量nCur内容。

For your confusion, Suppose if you have declared your struct as follows: 为了您的困惑,假设您已经按如下方式声明了结构:

typedef struct month_s
{
    char* name;
} month_st; 

Still by doing nCur = mNext; 还是做nCur = mNext; you copy sizeof(month_st)) bytes from mNext to nCur variable hence to only address copied as name is a pointer to a memory. 你将sizeof(month_st))字节从mNextnCur变量,因此只复制地址,因为name是一个指向内存的指针。

In this case complete array/memory (that you probably allocate dynamically) not copy this is called Shallow copy . 在这种情况下,完整的数组/内存(您可能动态分配)不复制它称为浅复制

You are confused because you think mCur and mNext are pointers to objects, while in fact they are objects. 你很困惑,因为你认为mCurmNext是指向对象的指针,而实际上它们是对象。 The struct month_s merely allocates space in memory for storing the month name. struct month_s仅在内存中分配空间以存储月份名称。 It does not allocate memory for storing a pointer to anything. 它没有为存储指向任何东西的指针分配内存。 Thus, when mCur is assigned the value of mNext , the entire object is copied as it is copied by value and not by reference. 因此,当mCur被分配的值mNext ,整个对象,因为它是由值拷贝而不是通过参考复制。

I have annotated your code for convenience: 为方便起见,我注释了您的代码:

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