Help understand the differences between #define, const and enum in C and C ++ at assembly level

Recently, I have been looking at build codes for #define, const and enum:

C-codes (#define):

3   #define pi 3  
4   int main(void)
5   {
6      int a,r=1;             
7      a=2*pi*r;
8      return 0;
9   }

assembler codes (for lines 6 and 7 in c-codes) generated by GCC:

6   mov $0x1, -0x4(%ebp)
7   mov -0x4(%ebp), %edx
7   mov %edx, %eax
7   add %eax, %eax
7   add %edx, %eax
7   add %eax, %eax
7   mov %eax, -0x8(%ebp)

C-codes (enumeration):

2   int main(void)
3   {
4      int a,r=1;
5      enum{pi=3};
6      a=2*pi*r;
7      return 0;
8   }

assembly codes (for lines 4 and 6 in c-codes) generated by GCC:

6   mov $0x1, -0x4(%ebp)
7   mov -0x4(%ebp), %edx
7   mov %edx, %eax
7   add %eax, %eax
7   add %edx, %eax
7   add %eax, %eax
7   mov %eax, -0x8(%ebp)

C codes (const):

4   int main(void)
5   {
6      int a,r=1;  
7      const int pi=3;           
8      a=2*pi*r;
9      return 0;
10  }

assembly codes (for lines 7 and 8 in c-codes) generated by GCC:

6   movl $0x3, -0x8(%ebp)
7   movl $0x3, -0x4(%ebp)
8   mov  -0x4(%ebp), %eax
8   add  %eax, %eax
8   imul -0x8(%ebp), %eax
8   mov  %eax, 0xc(%ebp)

I found that the use #defineand enumassembly codes are the same. The compiler uses 3 add commands to perform multiplication. However, when used const, the imul command is used. Does anyone know the reason for this?

+5
source share
5 answers

, #define enum 3 , add, 3. add reg,reg 2 , 6 0 3, , imul 4 . , , * 2 * 3, , , 2 3. ( , ).

#define enum , 3, .

  mov $0x1, -0x4(%ebp)    ; r=1
  mov -0x4(%ebp), %edx    ; edx = r
  mov %edx, %eax          ; eax = edx
  add %eax, %eax          ; *2
  add %edx, %eax          ; 
  add %eax, %eax          ; *3
  mov %eax, -0x8(%ebp)    ; a = eax

const int pi = 3, 3. 4 , imul,

 movl $0x3, -0x8(%ebp)     ; pi = 3
 movl $0x3, -0x4(%ebp)     ; r = 3? (typo?)
 mov  -0x4(%ebp), %eax     ; eax = r
 add  %eax, %eax           ; *2
 imul -0x8(%ebp), %eax     ; *pi
 mov  %eax, 0xc(%ebp)      ; a = eax

, . a , , ,

xor eax, eax  ; return 0

.

:

MSVC . , MSVC imul 6. 3, const int = 3, imul.

, - const vs define vs enum, .

+7

const , , . , . # define'ed , . .

0

pi , . , .

[edit] , , , , a , ; a volatile, .

const ++ , C , , ++.

0

++ , C, GCC 4.4.1:

const int pi = 3;

...

a=2*pi*r;
-   0x40132e    <main+22>:      mov    0xc(%esp),%edx
-   0x401332    <main+26>:      mov    %edx,%eax
-   0x401334    <main+28>:      shl    %eax
-   0x401336    <main+30>:      add    %edx,%eax
-   0x401338    <main+32>:      shl    %eax
-   0x40133a    <main+34>:      mov    %eax,0x8(%esp)

, pi :

#define pi 3
0

, - , . :

int literal(int r)
{
  return 2*3*r;
}
int enumeral(int r)
{
  enum { pi=3 };
  return 2*pi*r;
}
int constant(int r)
{
  const int pi=3;
  return 2*pi*r;
}

... Apple gcc 4.2 (, ); , , ( ), , C ++:

    movl    4(%esp), %eax
    leal    (%eax,%eax,2), %eax
    addl    %eax, %eax
    ret

Based on the comments on John Knoller's answer, it seems that you did not realize that the GCC command-line options are case-sensitive. Parameters capital O ( -O1, -O2, -O3, -Os) include optimization; lowercase o ( -o whatever) specify the output file. The construction -o2 -othingsilently ignores the part -O2and is written to thing.

0
source

All Articles