C 使用“指定结构,内部包含字符数组”=&引用;作品
我正在检查某人的代码,开发人员已将一个结构分配给另一个结构。结构包含一个字符数组。不知何故,这“起作用”,意味着结构A中的字符数组确实被复制到结构B(不是通过引用)。我完全困惑不解。s.o.能给我解释一下吗?我写了一个小程序来说明这个“问题”C 使用“指定结构,内部包含字符数组”=&引用;作品,c,arrays,struct,char,C,Arrays,Struct,Char,我正在检查某人的代码,开发人员已将一个结构分配给另一个结构。结构包含一个字符数组。不知何故,这“起作用”,意味着结构A中的字符数组确实被复制到结构B(不是通过引用)。我完全困惑不解。s.o.能给我解释一下吗?我写了一个小程序来说明这个“问题” #包括 #包括 /************************************** *有些定义和类型定义供以后使用 **************************************/ #定义最大长度(80) typedef结构月 {
#包括
#包括
/**************************************
*有些定义和类型定义供以后使用
**************************************/
#定义最大长度(80)
typedef结构月
{
字符名[MAX_LEN];
}月;;
/**************************************
*这一点很清楚。
**************************************/
使用字符串()的静态void
{
char mCur[MAX_LEN]={“Jan”};
char mNext[MAX_LEN]={“Feb”};
/**这不编译(当然)*/
//mCur=mNext;
/**我们需要一个指针/引用*/
char*pmCur=&mCur[0];
/**但现在我们“参照复制”*/
pmCur=&(mNext[0]);
/**…因此此更改也适用于pmCur*/
strcpy(mNext,“Mar”);
/**…所以pmCur现在是“Mar”*/
printf(“%s:%s\n”,函数,pmCur);
}
/**************************************
*我想是一样的。类似的
*就像上面发生的一样。但这“有效”。
*我很惊讶地看到这不是事实
*这个案子。有人能解释一下吗?
**************************************/
使用struct()的静态void
{
月份{“一月”};
第二个月{“二月”};
/**我本以为这是字符串的“引用复制”*/
mCur=mNext;
/**我本以为这也会覆盖mCur.name
因为它现在指向mNext.name*/
strcpy(mNext.name,“Mar”);
/**这是怎么回事???mCur.name仍然是“Feb”*/
printf(“%s:%s\n”,函数名,mCur.name);
}
/**************************************
*只是主要的
**************************************/
int main()
{
使用字符串();
使用struct();
返回0;
}
您可能最惊讶的是,数组和指针在C语言中不是一回事。在您的示例中,数组成员不仅包含指向字符串的指针,还包含字符串本身。因此,当您将一个struct
实例分配给另一个实例时,所有这些都会被复制。根据您的struct声明:
typedef struct month_s
{
char name[MAX_LEN];
} month_st;
sizeof(month\u st)
包括作为结构成员的char数组的空格。(注意,您正在进行静态内存分配,name
不是指针而是数组)。所以,当您将一个strct变量分配给另一个变量时,它会完全复制数组(或者我们可以说total
sizeof(month_st))
bytes将被复制)
接下来,您将声明两个结构变量:
month_st mCur = {"Jan"};
month_st mNext = {"Feb"};
变量mCur
和mNext
的内存不同。当你做作业时,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
是指向内存的指针
在这种情况下,完整的数组/内存(您可能会动态分配)不会复制,这称为浅层复制 您感到困惑,因为您认为
mCur
和mNext
是指向对象的指针,而实际上它们是对象。结构month\u 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);
}
关于指针和数组之间的区别,我看到了三种解释,但据我所知,它们似乎没有解决所提出的问题 据我所知,问题是:“我知道我不能将一个数组分配给另一个数组,所以如果数组位于结构中,为什么我可以这样做?” 答案基本上是“因为语言是这样说的”。尽管结构是聚合类型,并且很可能包含数组,但语言规范说结构是可分配的,因此结构是可分配的。这是第6.5.16.1节和中的简单赋值 (在后台,编译器可能必须实现内存拷贝,但这是编译器的问题,不是你的问题。)没有卷影拷贝,而是浅拷贝。
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);
}