Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
05/04/08 00:37
Modified:
  05/04/08 02:25

Read: times


 
Msg Score: +2
 +1 Good Answer/Helpful
 +1 Informative
#154357 - No
Responding to: ???'s previous message
Erik said:
if (buffer[index + 8] == 0x47)
index+8 figured at run time

if ((buffer + 8)[index] == 0x47)
buffer+8 figured at compile time

This might be true for some compilers, but it's certainly not true for all of them, and a person would be ill-advised to base his coding style on such a superstitious notion. Here's a quote from K&R (except that I changed 'i' to 'j' so the subscripts don't get mistaken for italics tags. Craig. ;-) ):

Kernighan and Ritchie said:
... a reference to a[j] can also be written as *(a+j). In evaluating a[j], C converts it to *(a+j) immediately; the two forms are completely equivalent.

If we apply that rule to Erik's examples, we see that

buffer[index+8] is equivalent to *(buffer+index+8), and
(buffer+8)[index] is equivalent to *(buffer+8+index).

So it's clear that a sufficiently smart compiler could, should, and would calculate buffer+8 at compile time in either case, regardless of whether the target processor was a '51 or a Pentium or a single-tape Turing machine. As an example, here's some output from Microsoft's hotdog C/C++ compiler for the 80x86:
        if (buffer[index + 8] == 0x47) break;

004113A1 0F B6 05 78 71 41 00  movzx     eax,byte ptr [index (417178h)] 
004113A8 0F B6 88 84 71 41 00  movzx     ecx,byte ptr buffer+8 (417184h)[eax] 
004113AF 83 F9 47              cmp       ecx,47h 
004113B2 75 02                 jne       wmain+56h (4113B6h) 
004113B4 EB 2C                 jmp       wmain+82h (4113E2h) 

        if ((buffer + 8)[index] == 0x47) break;

004113B6 0F B6 05 78 71 41 00  movzx     eax,byte ptr [index (417178h)] 
004113BD 0F B6 88 84 71 41 00  movzx     ecx,byte ptr buffer+8 (417184h)[eax] 
004113C4 83 F9 47              cmp       ecx,47h 
004113C7 75 02                 jne       wmain+6Bh (4113CBh) 
004113C9 EB 17                 jmp       wmain+82h (4113E2h) 

        if (buffer[index] == 0x47) break;

004113CB 0F B6 05 78 71 41 00  movzx     eax,byte ptr [index (417178h)] 
004113D2 0F B6 88 7C 71 41 00  movzx     ecx,byte ptr buffer (41717Ch)[eax] 
004113D9 83 F9 47              cmp       ecx,47h 
004113DC 75 02                 jne       wmain+80h (4113E0h) 
004113DE EB 02                 jmp       wmain+82h (4113E2h) 
Note that it generates essentially the same code for both of Erik's examples, as well as a third example where the "+ 8" is missing entirely.

Closer to home, the Keil compiler also gets it right, showing that there is no distinction to be made in this context between a "Real C" compiler (whatever that means) and one for "'51 C" (whatever that means).
C51 COMPILER V7.05, COMPILATION OF MODULE TEST
OBJECT MODULE PLACED IN test.OBJ
COMPILER INVOKED BY: C:\SiLabs\MCU\IDEfiles\C51\BIN\C51.exe test.c DB OE CD SB

stmt level    source

   1          unsigned char buffer[10];
   2          unsigned char index;
   3          
   4          void main() {
   5   1          for (index=0; index<=254; index++) {
   6   2              if (buffer[index + 8] == 0x47) break;
   7   2              if ((buffer + 8)[index] == 0x47) break;
   8   2              if (buffer[index] == 0x47) break;
   9   2              }
  10   1          }
  11          

ASSEMBLY LISTING OF GENERATED OBJECT CODE

             ; FUNCTION main (BEGIN)
                                           ; SOURCE LINE # 4
                                           ; SOURCE LINE # 5
0000 E4                CLR     A
0001 F500        R     MOV     index,A
0003         ?C0001:
                                           ; SOURCE LINE # 6
0003 7400        R     MOV     A,#LOW buffer+08H
0005 2500        R     ADD     A,index
0007 F8                MOV     R0,A
0008 E6                MOV     A,@R0
0009 FF                MOV     R7,A
000A 6447              XRL     A,#047H
000C 6018              JZ      ?C0007
000E         ?C0004:
                                           ; SOURCE LINE # 7
000E EF                MOV     A,R7
000F 6447              XRL     A,#047H
0011 6013              JZ      ?C0007
0013         ?C0005:
                                           ; SOURCE LINE # 8
0013 7400        R     MOV     A,#LOW buffer
0015 2500        R     ADD     A,index
0017 F8                MOV     R0,A
0018 E6                MOV     A,@R0
0019 6447              XRL     A,#047H
001B 6009              JZ      ?C0007
                                           ; SOURCE LINE # 9
001D         ?C0003:
001D 0500        R     INC     index
001F E500        R     MOV     A,index
0021 D3                SETB    C
0022 94FE              SUBB    A,#0FEH
0024 40DD              JC      ?C0001
                                           ; SOURCE LINE # 10
0026         ?C0007:
0026 22                RET     
-- Russ


List of 20 messages in thread
TopicAuthorDate
"Real C" vs '51 C            01/01/70 00:00      
   there is nothing wrong except...            01/01/70 00:00      
      if you are not , why are you even here            01/01/70 00:00      
         *(buffer+8+index)?            01/01/70 00:00      
            none of the above            01/01/70 00:00      
               OK then how?            01/01/70 00:00      
   like this            01/01/70 00:00      
      but it's basically the same...            01/01/70 00:00      
      YCMV            01/01/70 00:00      
      No            01/01/70 00:00      
         assumptions            01/01/70 00:00      
            Re: assumptions            01/01/70 00:00      
               I took a \'known\' example            01/01/70 00:00      
                  Compiler-independent efficient C            01/01/70 00:00      
                     a clarification and an example            01/01/70 00:00      
                        Two kinds of "efficiency"            01/01/70 00:00      
                     Compiler smarter than coder            01/01/70 00:00      
                        Getting the least out of your compiler            01/01/70 00:00      
   Real C is inherently reentrant            01/01/70 00:00      
      which, even when possible, often is ill advised            01/01/70 00:00      

Back to Subject List