How can variable initialization be more efficient? Check the disassembly code of the VC and GCC compilers to see the efficiency difference of initialization of different methods. The CL version of Windows compiler is Microsoft (r) 32-bit C/C ++ Optimizing Compiler version 12.00.8168 for 80x86, and GCC version is 4.5.3.
Source code:
void funA(){char *str1="helloworld";}void funB(){char str2[]="helloworld";}void funC(){char str3[11]="helloworld";}void funD(){char str4[11];str4[0]='h';str4[1]='e';str4[2]='l';str4[3]='l';str4[4]='o';str4[5]='w';str4[6]='o';str4[7]='r';str4[8]='l';str4[9]='d';str4[10]='\0';}void main(){funA();funB();funC();funD();}
1. VC Compilation: compile code generated by VC: CL/FA varinit. c
TITLED:\5test\VarInit\varInit.c.386Pinclude listing.incif @Version gt 510.model FLATelse_TEXTSEGMENT PARA USE32 PUBLIC 'CODE'_TEXTENDS_DATASEGMENT DWORD USE32 PUBLIC 'DATA'_DATAENDSCONSTSEGMENT DWORD USE32 PUBLIC 'CONST'CONSTENDS_BSSSEGMENT DWORD USE32 PUBLIC 'BSS'_BSSENDS_TLSSEGMENT DWORD USE32 PUBLIC 'TLS'_TLSENDSFLATGROUP _DATA, CONST, _BSSASSUMECS: FLAT, DS: FLAT, SS: FLATendifPUBLIC_funA_DATASEGMENT$SG32DB'helloworld', 00H_DATAENDS_TEXTSEGMENT_str1$ = -4_funAPROC NEAR; File D:\5test\VarInit\varInit.c; Line 2pushebpmovebp, esppushecx; Line 3movDWORD PTR _str1$[ebp], OFFSET FLAT:$SG32; Line 4movesp, ebppopebpret0_funAENDP_TEXTENDSPUBLIC_funB_DATASEGMENTORG $+1$SG36DB'helloworld', 00H_DATAENDS_TEXTSEGMENT_str2$ = -12_funBPROC NEAR; Line 7pushebpmovebp, espsubesp, 12; 0000000cH; Line 8moveax, DWORD PTR $SG36movDWORD PTR _str2$[ebp], eaxmovecx, DWORD PTR $SG36+4movDWORD PTR _str2$[ebp+4], ecxmovdx, WORD PTR $SG36+8movWORD PTR _str2$[ebp+8], dxmoval, BYTE PTR $SG36+10movBYTE PTR _str2$[ebp+10], al; Line 9movesp, ebppopebpret0_funBENDP_TEXTENDSPUBLIC_funC_DATASEGMENTORG $+1$SG40DB'helloworld', 00H_DATAENDS_TEXTSEGMENT_str3$ = -12_funCPROC NEAR; Line 12pushebpmovebp, espsubesp, 12; 0000000cH; Line 13moveax, DWORD PTR $SG40movDWORD PTR _str3$[ebp], eaxmovecx, DWORD PTR $SG40+4movDWORD PTR _str3$[ebp+4], ecxmovdx, WORD PTR $SG40+8movWORD PTR _str3$[ebp+8], dxmoval, BYTE PTR $SG40+10movBYTE PTR _str3$[ebp+10], al; Line 14movesp, ebppopebpret0_funCENDP_TEXTENDSPUBLIC_funD_TEXTSEGMENT_str4$ = -12_funDPROC NEAR; Line 17pushebpmovebp, espsubesp, 12; 0000000cH; Line 19movBYTE PTR _str4$[ebp], 104; 00000068H; Line 20movBYTE PTR _str4$[ebp+1], 101; 00000065H; Line 21movBYTE PTR _str4$[ebp+2], 108; 0000006cH; Line 22movBYTE PTR _str4$[ebp+3], 108; 0000006cH; Line 23movBYTE PTR _str4$[ebp+4], 111; 0000006fH; Line 24movBYTE PTR _str4$[ebp+5], 119; 00000077H; Line 25movBYTE PTR _str4$[ebp+6], 111; 0000006fH; Line 26movBYTE PTR _str4$[ebp+7], 114; 00000072H; Line 27movBYTE PTR _str4$[ebp+8], 108; 0000006cH; Line 28movBYTE PTR _str4$[ebp+9], 100; 00000064H; Line 29movBYTE PTR _str4$[ebp+10], 0; Line 30movesp, ebppopebpret0_funDENDP_TEXTENDSPUBLIC_main_TEXTSEGMENT_mainPROC NEAR; Line 33pushebpmovebp, esp; Line 34call_funA; Line 35call_funB; Line 36call_funC; Line 37call_funD; Line 38popebpret0_mainENDP_TEXTENDSEND
2. In the cygwin environment, GCC compiles and generates the assembly code: gcc-s varinit. c
.file"varInit.c".section .rdata,"dr"LC0:.ascii "helloworld\0".text.globl _funA.def_funA;.scl2;.type32;.endef_funA:pushl%ebpmovl%esp, %ebpsubl$16, %espmovl$LC0, -4(%ebp)leaveret.globl _funB.def_funB;.scl2;.type32;.endef_funB:pushl%ebpmovl%esp, %ebpsubl$16, %espmovl$1819043176, -11(%ebp)movl$1919907695, -7(%ebp)movw$25708, -3(%ebp)movb$0, -1(%ebp)leaveret.globl _funC.def_funC;.scl2;.type32;.endef_funC:pushl%ebpmovl%esp, %ebpsubl$16, %espmovl$1819043176, -11(%ebp)movl$1919907695, -7(%ebp)movw$25708, -3(%ebp)movb$0, -1(%ebp)leaveret.globl _funD.def_funD;.scl2;.type32;.endef_funD:pushl%ebpmovl%esp, %ebpsubl$16, %espmovb$104, -11(%ebp)movb$101, -10(%ebp)movb$108, -9(%ebp)movb$108, -8(%ebp)movb$111, -7(%ebp)movb$119, -6(%ebp)movb$111, -5(%ebp)movb$114, -4(%ebp)movb$108, -3(%ebp)movb$100, -2(%ebp)movb$0, -1(%ebp)leaveret.def___main;.scl2;.type32;.endef.globl _main.def_main;.scl2;.type32;.endef_main:pushl%ebpmovl%esp, %ebpandl$-16, %espcall___maincall_funAcall_funBcall_funCcall_funDmovl%ebp, %esppopl%ebpret
In general, the first method is the most efficient, because strings are directly defined in the Data Segment of the code and then directed to the register. The second and third methods indicate whether or not the array size is defined, the execution efficiency is the same, so if the string is directly initialized, the size is not defined to avoid the number of wrong lengths. The fourth one can be seen when only local variables are defined, without initialization, neither of the two platforms will call assembly code to do anything. Therefore, from the perspective of efficiency, Initialization is not allowed if Initialization is enabled. If Initialization is required, try to initialize it during definition. When storing strings, try to use an integer multiple of 4. If you write one or two \ 0 strings, you can reduce the number of Assembly commands. When the length is 11, 4*2 + 2 + 1 is used to store strings. If one \ 0 is written, one assembly instruction can be reduced. It is not verified on 64-bit machines, but it should be able to store 8 bytes of characters in one assembly command.
Comparing the compilation code of the two platforms, the compilation code comments compiled by VC should be detailed. However, for the second and third initialization operations on the VC platform, the temporary variables are first stored in eax and then in string variables. in GCC, the temporary variables are directly retrieved from EBP, there is one less command in the corresponding memory.