zoukankan      html  css  js  c++  java
  • 一个C/C++结构体初始化有趣的现象

    我们知道C语言当中结构可以使用{}进行初始化,例如有结构体定义如下:

    typedef struct type_t {
    	int a;
    	int b;
    	int c;
    	int d;
    }type_t;
    

    我们可以使用下面的语句来初始化一个变量:

    struct type_t o = { 1, 2, 3, 4 }


    但是如果像下面这样来初始化,结果会是什么呢?

    type_t o = { 8, o.a, o.b, o.c };


    其结果是依赖于编译器的实现,笔者分别在VS2010和GCC下进行了测试,结果如下:

    1. vs2010下C和C++的结果都是:

    o.a = 8, o.b = 8, o.c = 8, o.d = 8

    2. GCC的C编译运行结果:

    o.a = 8 o.b = 0, o.c = 0, o.d = 4195296

    3. GCC的C++编译运行结果:

    o.a = 8, o.b = 8, o.c = 8, o.d = 8


    为啥会这样呢?带着疑问,笔者又去看了一下反汇编的代码,VS2010的反汇编代码如下:

    	type_t o = { 8, o.a, o.b, o.c };
    004113A8  mov         dword ptr [ebp-18h],8  
    004113AF  mov         eax,dword ptr [ebp-18h]  
    004113B2  mov         dword ptr [ebp-14h],eax  
    004113B5  mov         eax,dword ptr [ebp-14h]  
    004113B8  mov         dword ptr [ebp-10h],eax  
    004113BB  mov         eax,dword ptr [ebp-10h]  
    004113BE  mov         dword ptr [ebp-0Ch],eax  

    这段代码翻译过来的意思就是:

    o.a = 8;
    eax = o.a
    o.b = eax
    eax = o.b
    o.c = eax
    eax = o.c
    o.d = eax


    gcc编译的反汇编代码:

    => 0x00000000004004cd <+9>:     mov    -0x20(%rbp),%ecx
       0x00000000004004d0 <+12>:    mov    -0x1c(%rbp),%edx
       0x00000000004004d3 <+15>:    mov    -0x18(%rbp),%eax
       0x00000000004004d6 <+18>:    movl   $0x8,-0x20(%rbp)
       0x00000000004004dd <+25>:    mov    %ecx,-0x1c(%rbp)
       0x00000000004004e0 <+28>:    mov    %edx,-0x18(%rbp)
       0x00000000004004e3 <+31>:    mov    %eax,-0x14(%rbp)

    这段代码可翻译如下:

    ecx=o.a
    edx=o.b
    eax=o.c
    o.a=8
    o.b=ecx
    o.c=edx
    o.d=eax


    g++编译的反汇编代码:

    => 0x00000000004005ad <+9>:     movq   $0x0,-0x20(%rbp)
       0x00000000004005b5 <+17>:    movq   $0x0,-0x18(%rbp)
       0x00000000004005bd <+25>:    movl   $0x8,-0x20(%rbp)
       0x00000000004005c4 <+32>:    mov    -0x20(%rbp),%eax
       0x00000000004005c7 <+35>:    mov    %eax,-0x1c(%rbp)
       0x00000000004005ca <+38>:    mov    -0x1c(%rbp),%eax
       0x00000000004005cd <+41>:    mov    %eax,-0x18(%rbp)
       0x00000000004005d0 <+44>:    mov    -0x18(%rbp),%eax
       0x00000000004005d3 <+47>:    mov    %eax,-0x14(%rbp)

    这段代码翻译如下:

    将o变量清零
    o.a = 8;
    eax = o.a
    o.b = eax
    eax = o.b
    o.c = eax
    eax = o.c
    o.d = eax


    现在该完全清楚了,g++和vs2010生成的汇编指令基本一致,都是先将前一个成员初始化后再进行取值。而gcc则是先将o的成员变量值全部保存的寄存器中,然后逐一对o变量进行初始化。

    但是所不明白的是为何gcc要这样生成指令?



  • 相关阅读:
    网站设计的65条原则
    汇编指令: VERW、WAIT、WBINVD、WRSHR、WRMSR、XADD、XBTS、XCHG、
    openssl编程入门(含完整可编译和运行示例)
    揭开Linux的Swap之谜
    成功的 Web 应用系统性能测试
    加密通讯协议SSL编程周立发
    Google Sparse Hash
    测试 Linux 的可靠性
    进程绑定CPU简单应用
    mylarge&mymedium&mysmall&myinnodbheavy4G
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3214958.html
Copyright © 2011-2022 走看看