This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

typedef & optimisation

In the book "TCP/IP Lean" [1], the author states:

"I have used #define in preference to typedef because compilers use better optimisation strategies for their native data types."

Is this true of the Keil C51 compiler?

ie, will C51 generate better-optimised code from source using

#define U8 unsigned char
than from source using
typedef unsigned char U8

[1] Bentham, J.
"TCP/IP Lean"
CMP Books, 2000
ISBN 1-929629-11-7
http://www.iosoft.co.uk/tcplean.htm

  • Andrew,

    I'm quite keen to know the answer to this also; not only for C51, but for other compilers in general, since I use many. This would be a good question to post on USENET's comp.lang.c.moderated also. Folks that actually implement compilers often lurk there. Maybe comp.arch.embedded too. In fact Mr. Bentham is involved in a dialog there now regarding TCP/IP for 8-bitters.

    Not wanting to steal your question, I wonder, would you consider posting to one or both of the above newsgroups?

    --Dan Henry

  • There are two traditional places to optimize the code generated by a C program.

    In the front-end. This involves optimizing the program from the aspect of the C source code.

    In the back-end. This involves optimizing the program from the aspect of the intermediate or assembly code generated.

    Since most of the serious optimizations are done in the back-end of the compiler, whether you use typedef or #define is immaterial.

    To test this, I created a simple program:

    #include <stdio.h>
    
    typedef unsigned int WORD1;
    #define WORD2 unsigned int
    
    void tst_typedef (void)
    {
    WORD1 i;
    
    for (i = 0; i < 1000; i++)
      {
      printf ("i = %u\n", i);
      printf ("2i = %u\n", 2 * i);
      }
    }
    
    void tst_define (void)
    {
    WORD2 i;
    
    for (i = 0; i < 1000; i++)
      {
      printf ("i = %u\n", i);
      printf ("2i = %u\n", 2 * i);
      }
    }
    
    void main (void)
    {
    tst_typedef ();
    tst_define ();
    
    while (1);
    }
    

    which I ran and generated assembler output.

    ASSEMBLY LISTING OF GENERATED OBJECT CODE
    
    
                 ; FUNCTION tst_typedef (BEGIN)
                                               ; SOURCE LINE # 6
                                               ; SOURCE LINE # 7
                                               ; SOURCE LINE # 10
    0000 E4                CLR     A
    0001 F500        R     MOV     i,A
    0003 F500        R     MOV     i+01H,A
    0005         ?C0001:
                                               ; SOURCE LINE # 11
                                               ; SOURCE LINE # 12
    0005 7BFF              MOV     R3,#0FFH
    0007 7A00        R     MOV     R2,#HIGH ?SC_0
    0009 7900        R     MOV     R1,#LOW ?SC_0
    000B 850000      E     MOV     ?_printf?BYTE+03H,i
    000E 850000      E     MOV     ?_printf?BYTE+04H,i+01H
    0011 120000      E     LCALL   _printf
                                               ; SOURCE LINE # 13
    0014 7BFF              MOV     R3,#0FFH
    0016 7A00        R     MOV     R2,#HIGH ?SC_8
    0018 7900        R     MOV     R1,#LOW ?SC_8
    001A E500        R     MOV     A,i+01H
    001C 25E0              ADD     A,ACC
    001E F500        E     MOV     ?_printf?BYTE+04H,A
    0020 E500        R     MOV     A,i
    0022 33                RLC     A
    0023 F500        E     MOV     ?_printf?BYTE+03H,A
    0025 120000      E     LCALL   _printf
                                               ; SOURCE LINE # 14
    0028 0500        R     INC     i+01H
    002A E500        R     MOV     A,i+01H
    002C 7002              JNZ     ?C0012
    002E 0500        R     INC     i
    0030         ?C0012:
    0030 C3                CLR     C
    0031 94E8              SUBB    A,#0E8H
    0033 E500        R     MOV     A,i
    0035 9403              SUBB    A,#03H
    0037 40CC              JC      ?C0001
                                               ; SOURCE LINE # 15
    0039         ?C0004:
    0039 22                RET     
                 ; FUNCTION tst_typedef (END)
    
                 ; FUNCTION tst_define (BEGIN)
                                               ; SOURCE LINE # 17
                                               ; SOURCE LINE # 18
                                               ; SOURCE LINE # 21
    0000 E4                CLR     A
    0001 F500        R     MOV     i,A
    0003 F500        R     MOV     i+01H,A
    0005         ?C0005:
                                               ; SOURCE LINE # 22
                                               ; SOURCE LINE # 23
    0005 7BFF              MOV     R3,#0FFH
    0007 7A00        R     MOV     R2,#HIGH ?SC_0
    0009 7900        R     MOV     R1,#LOW ?SC_0
    000B 850000      E     MOV     ?_printf?BYTE+03H,i
    000E 850000      E     MOV     ?_printf?BYTE+04H,i+01H
    0011 120000      E     LCALL   _printf
                                               ; SOURCE LINE # 24
    0014 7BFF              MOV     R3,#0FFH
    0016 7A00        R     MOV     R2,#HIGH ?SC_8
    0018 7900        R     MOV     R1,#LOW ?SC_8
    001A E500        R     MOV     A,i+01H
    001C 25E0              ADD     A,ACC
    001E F500        E     MOV     ?_printf?BYTE+04H,A
    0020 E500        R     MOV     A,i
    0022 33                RLC     A
    0023 F500        E     MOV     ?_printf?BYTE+03H,A
    0025 120000      E     LCALL   _printf
                                               ; SOURCE LINE # 25
    0028 0500        R     INC     i+01H
    002A E500        R     MOV     A,i+01H
    002C 7002              JNZ     ?C0013
    002E 0500        R     INC     i
    0030         ?C0013:
    0030 C3                CLR     C
    0031 94E8              SUBB    A,#0E8H
    0033 E500        R     MOV     A,i
    0035 9403              SUBB    A,#03H
    0037 40CC              JC      ?C0005
                                               ; SOURCE LINE # 26
    0039         ?C0008:
    0039 22                RET     
                 ; FUNCTION tst_define (END)
    
                 ; FUNCTION main (BEGIN)
                                               ; SOURCE LINE # 29
                                               ; SOURCE LINE # 30
                                               ; SOURCE LINE # 31
    0000 120000      R     LCALL   tst_typedef
                                               ; SOURCE LINE # 32
    0003 120000      R     LCALL   tst_define
    0006         ?C0009:
                                               ; SOURCE LINE # 34
    0006 80FE              SJMP    ?C0009
                 ; FUNCTION main (END)
    
    

    As you can see, the 2 functions tst_define and tst_typedef generate identical code.

    This is only a simple test, but I'm pretty certain you won't find any differences between using #define and typedef.

    Jon

  • Thanks, Jon. This is consistent with my limited knowledge of compiler design. The compiler knows how to deal with objects and expressions having particular characteristics, with size and "type" being among those characteristics. It should not make any difference whether a compiler learns about an object having one of the "native" types directly through a macro expansion or by "looking back" to resolve a typedef. Two objects having the same "root type" should be treated the same.

    Of course, I could be wrong entirely. ;-)

    --Dan Henry