C語言中結構體直接賦值?

茫茫大士發表於2018-10-21

FROM:http://codewenda.com/c語言結構體直接賦值/

在C語言中結構體變數之間可以進行賦值操作嗎?

簡單結構體的賦值

先說結論:一般來說,C語言中的結構體變數可以用另一個變數對其進行賦值或初始化。簡單結構體(不包含指標成員)直接賦值沒有問題。
我們先下面一段程式碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#include <stdio.h>

#include <stdlib.h>

 

struct MyStruct

{

    int a;

    int b;

    char c[10];

};

 

int main()

{

    struct MyStruct t1 = {1, 2, "hello"};

    struct MyStruct t2 = {3, 4, "world"};

    t2 = t1; //將t1賦值給t2

    printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);

    printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);

 

    return 0;

}

以上程式碼的輸出為:

1

2

MyStruct t1: 1, 2, hello

MyStruct t2: 1, 2, hello

以上用t1給t2進行初始化,結果也相同。可以看到簡單的結構體(結構體的成員沒有指標成員)變數之間直接賦值是沒有問題的。

有指標成員的結構體賦值

而通常情況下,稍微複雜一點的結構體裡面會有指標成員,那麼以上的淺拷貝則會有問題了,我們假設MyStruct裡面的成員c不是陣列,而是字元指標,會有什麼問題呢?
看如下程式碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

struct MyStruct

{

    int a;

    int b;

    char* c;

};

 

int main()

{

    struct MyStruct t1;

    t1.a = 1;

    t1.b = 2;

    // 為指標區域賦值

    char *p = (char*)malloc(10*sizeof(char));

    strcpy(p, "hello");

    t1.c = p;

 

    struct MyStruct t2;

    t2 = t1;

    printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);

    // 釋放了t1的記憶體

    // free(p);

    printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);

 

 

    printf("t1 pointer addr: %p\n", t1.c);

    printf("t2 pointer addr: %p\n", t2.c);

 

    return 0;

}

上面的輸出結果為:

1

2

3

4

MyStruct t1: 1, 2, hello

MyStruct t2: 1, 2, hello

t1 pointer addr: 0x6000284d0

t2 pointer addr: 0x6000284d0

可以看到,賦值會直接將t1的指標變數賦值給t2.c,如果我們在賦值之後將t1所用的資源釋放掉,那麼使用t2的話則可能導致記憶體洩漏了。如果上面的程式碼,我們沒有註釋掉 free(p);,那麼輸出t2時結果這不確定了:

1

2

3

4

MyStruct t1: 1, 2, hello

MyStruct t2: 1, 2, (/.?

t1 pointer addr: 0x6000284d0

t2 pointer addr: 0x6000284d0

 

所以,如果struct中有指標成員,那麼結構體賦值不能簡單的直接複製了,而需要為指標成員另外分配記憶體,並將資料拷貝過去,當然我們可以將這些處理封裝在單獨的函式中來完成。
示例程式碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

struct MyStruct

{

    int a;

    int b;

    char* c;

};

 

int main()

{

    struct MyStruct t1;

    t1.a = 1;

    t1.b = 2;

    // 為指標區域賦值

    char *p = (char*)malloc(10*sizeof(char));

    strcpy(p, "hello");

    t1.c = p;

 

    struct MyStruct t2;

    // 各個成員分別賦值,可以進行封裝

    t2.a = t1.a;

    t2.b = t1.b;

    char *p2 = (char*)malloc(10*sizeof(char));

    strcpy(p2, t1.c);

    t2.c = p2;

 

    printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);

    // 釋放了t1的記憶體

    free(p);

    printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);

 

    printf("t1 pointer addr: %p\n", t1.c);

    printf("t2 pointer addr: %p\n", t2.c);

 

    return 0;

}

以上程式碼輸出結果為:

1

2

3

4

MyStruct t1: 1, 2, hello

MyStruct t2: 1, 2, hello

t1 pointer addr: 0x6000284d0

t2 pointer addr: 0x600062e10

 

相關文章