2013-07-27 32 views
4

我正在评审某人的代码,开发人员已将一个结构分配给另一个结构。该结构包含一个char数组。不知何故“有效”,意味着来自结构A的char数组不会被复制到结构B(不是通过引用)。我完全困惑。可以s.o.向我解释一下?我写了一个小程序来说明“问题”。使用“=”分配结构与char数组里面的作品?

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

回答

2

我看到关于指针和数组的区别三种解释,但他们似乎没有解决被问的问题,据我所知。

的问题,我的理解是:“我知道,我不能一个数组赋值给另一个,为什么可以我做到这一点,如果数组是一个结构里面?”

答案基本上是“因为语言这么说”。即使结构体是一个聚合类型,并且可能包含一个数组,但语言规范说结构体是可赋值的,因此结构体是可赋值的。这是N1256N1570中的部分6.5.16.1 Simple assignment

(引擎盖下,编译器可能需要实现一个内存拷贝,但是这是编译器的问题,不是你的。)

3

你是什么人可能最惊讶的是,数组和指针不是C.一个数组成员同样的事情,在你的例子不仅包含一个指向字符串,但字符串本身。因此,当您将一个struct实例分配给另一个实例时,所有论文都会被复制。

1

根据你的结构的声明:

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"); 

影响仅可变nCur的变量mNext,它不改变内容。

对于你的困惑,假设如果你已经宣布你的结构如下:

typedef struct month_s 
{ 
    char* name; 
} month_st; 

在边做边nCur = mNext;sizeof(month_st))字节,因此复制从mNextnCur变量只被复制为name地址是一个指向记忆。

在这种情况下完整的数组/内存(你可能动态分配)不复制这个被称为浅拷贝

+1

没有***影复制***有一个** *浅拷贝***。 –

+0

@AlokSave谢谢! –

0

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