C語言用結構體給另一個同類型結構體賦值: 用等號即可

看到很多C代碼的結構體賦值都是用memcpy函數來拷貝,其實根本不需要,用等號直接賦值即可。結構體描述的是的一塊連續內存的內存佈局,同類型的一個結構體變量給另一個結構體變量賦值,使用等號編譯不會有任何問題,其效果顯然也和人直覺認爲的一樣,拷貝對應內存。

通過反彙編看編譯器的行爲,效果跟memcpy一樣,還省掉了函數調用開銷,代碼更加的簡潔明瞭。

// @file: main.c
struct node {
    long a;
    int  b;
    char c;
    long array[3];
}; 
int main() {
    struct node n1;
    n1.a = 1;
    n1.b = 2;
    n1.c = 3;
    n1.array[0] = 10;
    n1.array[1] = 11;
    n1.array[2] = 12;
    struct node n2 = n1;
    return 0;
}

運行查看其行爲:

(gdb)Breakpoint 1, main () at main.c:17
        17      return 0;
(gdb) p n1
$1 = {a = 1, b = 2, c = 3 '\003', array = {10, 11, 12}}
(gdb) p n2
$2 = {a = 1, b = 2, c = 3 '\003', array = {10, 11, 12}}
(gdb) p &n1
$3 = (struct node *) 0x7fffffffe2d0
(gdb) p &n2
$4 = (struct node *) 0x7fffffffe300
(gdb) p sizeof(n1)
$5 = 40
(gdb) p $rbp
$6 = (void *) 0x7fffffffe330
(gdb) disass
Dump of assembler code for function main:
   0x000055555555466a <+0>:     push   %rbp
   0x000055555555466b <+1>:     mov    %rsp,%rbp
   0x000055555555466e <+4>:     sub    $0x60,%rsp
   0x0000555555554672 <+8>:     mov    %fs:0x28,%rax
   0x000055555555467b <+17>:    mov    %rax,-0x8(%rbp)
   0x000055555555467f <+21>:    xor    %eax,%eax
   0x0000555555554681 <+23>:    movq   $0x1,-0x60(%rbp) // &n1 0x..2d0
   0x0000555555554689 <+31>:    movl   $0x2,-0x58(%rbp)
   0x0000555555554690 <+38>:    movb   $0x3,-0x54(%rbp)
   0x0000555555554694 <+42>:    movq   $0xa,-0x50(%rbp)
   0x000055555555469c <+50>:    movq   $0xb,-0x48(%rbp)
   0x00005555555546a4 <+58>:    movq   $0xc,-0x40(%rbp) // n1.array[2] = 12;
   0x00005555555546ac <+66>:    mov    -0x60(%rbp),%rax
   0x00005555555546b0 <+70>:    mov    -0x58(%rbp),%rdx
   0x00005555555546b4 <+74>:    mov    %rax,-0x30(%rbp) // &n2 0x..300
   0x00005555555546b8 <+78>:    mov    %rdx,-0x28(%rbp)
   0x00005555555546bc <+82>:    mov    -0x50(%rbp),%rax
   0x00005555555546c0 <+86>:    mov    -0x48(%rbp),%rdx
   0x00005555555546c4 <+90>:    mov    %rax,-0x20(%rbp)
   0x00005555555546c8 <+94>:    mov    %rdx,-0x18(%rbp)
   0x00005555555546cc <+98>:    mov    -0x40(%rbp),%rax
   0x00005555555546d0 <+102>:   mov    %rax,-0x10(%rbp)
=> 0x00005555555546d4 <+106>:   mov    $0x0,%eax
   0x00005555555546d9 <+111>:   mov    -0x8(%rbp),%rdx
   0x00005555555546dd <+115>:   xor    %fs:0x28,%rdx
   0x00005555555546e6 <+124>:   je     0x5555555546ed <main+131>
   0x00005555555546e8 <+126>:   callq  0x555555554540 <__stack_chk_fail@plt>
   0x00005555555546ed <+131>:   leaveq
   0x00005555555546ee <+132>:   retq
End of assembler dump.
*/

而對於結構體的比較,是要具體到基本數據類型的結構體成員比較,因爲有字節對齊,用memcmp是不可靠。除非結構體顯示聲明單字節對齊,如用__attribute__((packed))修飾了結構體定義。

補充兩個資料:
C Programming Resource Center
C99 Standard

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章