编辑:修正了注释中提到的bug,问题仍然存在,所以这个问题并不是真的重复--只是我的C编程技巧在这一点上不是很好,下面给出的解决方案回答了这个问题,并且没有解决局部变量错误。
警告:C语言很新
我知道,当我们将一个结构分配给另一个结构时,就会执行一个浅拷贝。不过,我不明白为何会出现这样的情况:
假设下面我尝试初始化一个结构,通过使用赋值操作符将它称为Type2结构,Type1成员,那么应该已经执行了一个浅拷贝。这意味着复制Type2成员的地址:
typedef struct {
uint8_t someVal;
} Type1
typedef struct {
Type1 grid[3][3];
} Type2
//Constructor for Type2 "objects"
Type2 Type2_Constructor(void) {
Type1 empty = {.value = o}
Type2 newType2;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
//Shallow copy empty struct
newType2.grid[i][j] = empty;
}
return newType2;
}
int main (void) {
Type2 type2Object = Type2_Constructor();
for (int i = 0; i < 3; i ++)
for (int j = 0; j < 3; j++){
printf("%u",type2OBject.grid[i][j].value);
printf("\n\r%p\n\r",&(type2Object.grid[i][j].value));
printf("\n\r");
}
return 0;
}我希望看到:
0
0xMemoryLocation
0
0xMemoryLocation
0
0xMemoryLocation
.
.
.实际上,我看到的是这样的情况,地址增加了2个字节:
0
0x7fff57eaca18
0
0x7fff57eaca1a
0
0x7fff57eaca1c
0
0x7fff57eaca1e
0
0x7fff57eaca20
.
.
.既然浅拷贝应该直接复制地址,为什么&(type2Object.gridi.value)不同?
谢谢你的帮助!
发布于 2016-10-25 11:57:22
你似乎误解了什么是浅薄/深拷贝。一个浅拷贝将复制每个成员(或者按位复制(如果愿意)。深度复制还会复制结构的自有资源。
让我们从一个简单的例子开始:
struct X {
int val;
};
X x1 = {24};
X x2 = {42};
x1 = x2;是的,内建赋值运算符=确实执行一个浅拷贝.这意味着上述内容相当于:
x1.val = x2.val;在这种情况下,由于X没有,它没有外部资源,所以它也被认为是一个深拷贝,因为x2拥有的每一个东西都被复制到x1。这是X不拥有任何外部资源的结果。
当X拥有外部资源/例如:
struct X {
int *my_very_own_external_value;
};
X x1, x2;
x1.my_very_own_external_value = malloc(sizeof(int));
*x1.my_very_own_external_value = 24;
x2.my_very_own_external_value = malloc(sizeof(int));
*x2.my_very_own_external_value = 42;一个浅显的副本是这样的:
x1 = x2;这相当于:
x1.my_very_own_external_value = x2.my_very_own_external_value;如果您理解指针意味着x1丢失了它分配的内存的地址(谁持有24),现在x1和x2都有指向为x2分配的内存的指针,即存储42的内存;
如果你想要一份深刻的副本,你需要写:
free(x1.my_very_own_external_value);
x1.my_very_own_external_value = malloc(sizeof(int));
*x1.my_very_own_external_value = *x2.my_very_own_external_value;现在,您已经复制了x2外部拥有的内存(外部资源)。
免责声明:我可能是用C++风格写的
发布于 2016-10-25 12:01:37
您的代码有一个bug:
//Constructor for Type2 "objects"
Type2 * Type2_Constructor(void) {
Type1 empty = ...;
Type2 newType2;
... do something ...
Type2 * newType2Ptr = &newType2;
return newType2Ptr;
}newType2是一个局部变量--一个在堆栈上定义的结构。然后将其地址返回给调用函数。一旦退出Type2_Constructor函数,它的堆栈就不再掌握在您手中了。
当您从这个区域打印值时,您会得到各种各样的东西(您可能希望得到一个核心转储,但遗憾的是,情况并不总是这样)。
https://stackoverflow.com/questions/40238872
复制相似问题