2016-04-25 56 views
1

我測試淺拷貝的結構與此代碼:爲什麼結構淺拷貝不起作用?

#include "stdio.h" 
#include "conio.h" 

int main() { 

    struct str { 
     char * name; 
     int value; 
    }; 

    struct str str_1 = {"go", 255}; 
    struct str str_2; 

    str_2 = str_1; 

    str_1.name = "back"; 

    printf("%s\n",str_1.name); 
    printf("%s\n",str_2.name); 

    printf("\n"); 
    system("pause"); 
    return 0; 
} 

我期待的結果應該是:

back 
back 

但它是:

back 
go 

編輯:我預計,因爲淺拷貝,str_1.namestr_2.name應該始終指向相同的pla CE。

編輯:並與動態分配的,我得到了我的預期:

#include <stdio.h> 
#include <conio.h> 
#include <string.h> 

int main() { 

    struct str { 
     char * name; 
     int value; 
    }; 

    struct str str_1; 
    struct str str_2; 

    str_1.name = (char*) malloc(5); 
    strcpy(str_1.name,"go"); 

    str_2 = str_1; 

    strcpy(str_1.name,"back"); 

    printf("%s\n",str_1.name); 
    printf("%s\n",str_2.name); 

    printf("\n"); 
    system("pause"); 
    return 0; 
} 

結果是:

back 
back 

什麼是我誤會嗎?

+3

我不知道。你爲什麼期望你的預期?這不是什麼「淺」的意思... –

+1

恕我直言,這個問題沒有錯。 「顯而易見度」的程度不應該吸引downvotes。廣義相對論對一些民間人士來說顯而易見 – Bathsheba

+2

@Bathsheba:沒錯,但描述期望的缺乏吸引了低估。很難解釋爲什麼這個世界不符合隱藏的期望。 –

回答

2

拿一張紙,慢慢地畫出你認爲正在發生的每一步,這應該變得清晰。

讓我們畫struct str像這樣:

--------------------- 
| const char * name | 
--------------------- 
| int value   | 
--------------------- 

而且,我們表示在地址0xabcdef10爲這樣的字符串:

--0xabcdef10--------------------- 
| "string\0"     | 
--------------------------------- 

所以,當我們初始化str_1,我們需要一些內存位置將舉行「去」,讓我們打電話0xaaaaaa00

--0xaaaaaa00--------------------- 
| "go\0"      | 
--------------------------------- 

然後我們初始化str_1用一個指針:

struct str str_1 = {"go", 255}; 

--str_1--------------------------- 
| const char * name = 0xaaaaaa00 | 
---------------------------------- 
| int value = 255    | 
---------------------------------- 

現在我們採取的str_1淺拷貝,並將其命名爲str_2

--str_2--------------------------- 
| const char * name = 0xaaaaaa00 | 
---------------------------------- 
| int value = 255    | 
---------------------------------- 

接下來我們執行str_1.name = "back";。和以前一樣,我們首先要創建新的字符串。讓我們把這點0xbbbbbb00

--0xbbbbbb00--------------------- 
| "back\0"      | 
--------------------------------- 

然後我們將其分配給str_1.name,所以str_1現在看起來像:

--str_1--------------------------- 
| const char * name = 0xbbbbbb00 | 
---------------------------------- 
| int value = 255    | 
---------------------------------- 

請注意,我們沒有改變str_2

所以,當我們在看我們的最後的「記憶」中,我們看到:

--0xaaaaaa00--------------------- 
| "go\0"      | 
--------------------------------- 
    .... 

--0xbbbbbb00--------------------- 
| "back\0"      | 
--------------------------------- 
    .... 
--str_1--------------------------- 
| const char * name = 0xbbbbbb00 | 
---------------------------------- 
| int value = 255    | 
--str_2--------------------------- 
| const char * name = 0xaaaaaa00 | 
---------------------------------- 
| int value = 255    | 
---------------------------------- 

在新的字符串,所以str_1點,str_2點,老的字符串。

如果你描述爲動態的,你永遠不會更新結構中的指針,你可以通過相同的練習來找出在這種情況下發生的內存情況。

2

str_2 = str_1;確實採取淺拷貝。

但這並不意味着,任何後續改動什麼name指向str_1會自動反映在str_2

(真的,您應該使用const char*作爲字符串類型,因爲您正在分配只讀字符串文字)。

+0

我已經用動態分配案例編輯了這個問題,你能否在我的答案中更多地展示我? – Nik

1

str_2 = str_1;生成結構本身的硬拷貝。例如,value成員對於每個結構都是唯一的。

但是你得到了任何指針成員的軟拷貝,因爲拷貝不會影響任何指針的指向數據。意思是在複製之後,str_1str_2的指針name指向文字"go"

然後str_1.name = "back";只在str_1.name指向的地方變化。它不會改變str_2.name指向哪裏。

當您使用malloc和strcpy時,您更改指向的數據並獲取所有內容的完整硬拷貝。