Thread: Register and For loop

  1. #1
    Registered User
    Join Date
    Dec 2010
    Posts
    113

    Register and For loop

    I have two different questions:

    1. I have got a book: C The Complete Reference. It says when I declare a variable as register it can be accessed faster. Also I don't need to worry about the limit, because compiler stores some variables unregistered if the limit is reached. Then isn't there any disadvantage of register. Should I declare all local variables as register?

    2. There is a for loop:

    Code:
    int int pwr(register int m, register int e)
    {
    register int temp;
    temp = 1;
    for(; e; e--) temp = temp * m;
    return temp;
    }
    I haven't understood (; e; e--)

    What is the second part of this (e) here. What does it mean?

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    There's also no advantage to register, as the compiler is not obligated to put anything in a register either.

    The second part of the for-loop guard, like all for-loop guards, is the when-to-stop condition. The loop will continue while the second part evaluates true.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by GokhanK View Post
    I have two different questions:

    1. I have got a book: C The Complete Reference. It says when I declare a variable as register it can be accessed faster. Also I don't need to worry about the limit, because compiler stores some variables unregistered if the limit is reached. Then isn't there any disadvantage of register. Should I declare all local variables as register?
    You could but it's not advisable to interfere with optimizations the compiler/assembler can do because they are really good at it.
    Assigning locals to registers effectively shuts off those registers from the compiler's reach for code generation and optimisation.
    Quote Originally Posted by GokhanK View Post
    2. There is a for loop:

    Code:
    int int pwr(register int m, register int e)
    {
    register int temp;
    temp = 1;
    for(; e; e--) temp = temp * m;
    return temp;
    }
    I haven't understood (; e; e--)

    What is the second part of this (e) here. What does it mean?
    The for loop kicks off with whatever e is passed to pwr(); each loop decrements e until the terminal condition is reached i.e. e == 0.

  4. #4
    Registered User
    Join Date
    Dec 2010
    Posts
    113
    Quote Originally Posted by tabstop View Post
    There's also no advantage to register, as the compiler is not obligated to put anything in a register either.

    The second part of the for-loop guard, like all for-loop guards, is the when-to-stop condition. The loop will continue while the second part evaluates true.
    Then is the usage of register redundant?

    And I think I should give details about my second question:

    I have seen for statements as (e=1; e>5; e++), but I don't know what it means when e stands alone.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by GokhanK View Post
    Then is the usage of register redundant?
    No, but only use it if you know you can out-optimize your compiler, which is doubtful, or you have some other, really, really good reason I can't think of.

    I have seen for statements as (e=1; e>5; e++), but I don't know what it means when e stands alone.
    The middle expression is evaluated as a boolean expression, where true means keep looping and false means stop the loop. Boolean expressions in C are false when the expression is zero and true for all non-zero values. The expression 'e' just means "the value of e". So your for loop looks like:
    Code:
    for (no initialization; so long as e is true (non-zero); decrement e)
    EDIT: This pseudo code reflects your original loop, not your new bogus one that never executes because e is initialized to 1 and only loops if e > 5.

  6. #6
    Registered User
    Join Date
    Dec 2010
    Posts
    113
    Quote Originally Posted by anduril462 View Post

    EDIT: This pseudo code reflects your original loop, not your new bogus one that never executes because e is initialized to 1 and only loops if e > 5.
    Yes it is wrong. I should write e<5.

    Thanks for your nice reply.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    The best thing you can do with your book is throw it into the shredder.
    bullschildt

    It might be an easy read, but then again, most works of fiction without any basis in the real world are designed to be an easy read.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by GokhanK View Post
    I have two different questions:

    1. I have got a book: C The Complete Reference. It says when I declare a variable as register it can be accessed faster.
    register is an optimzation parameter that asks --not tells-- the compiler to reserve a CPU register for that variable... so that it doesn't have to be fetched from memory or the stack on repeated operations. Consider the following....

    Code:
    register int y = 0;
    int *z = &y;
    
    for (int x = 0; x < 10; x++)
      { y = x;
         if (x==5)
           *z = 100;  }
    Keeping in mind that y is in a CPU register while the loop executes, what is the actual value of y when that loop ends?

    It may sound like a really cool optimization, but if not used with caution, it can also introduce subtle, almost untraceable bugs into a program...
    Last edited by CommonTater; 01-20-2011 at 11:45 AM.

  9. #9
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by Salem View Post
    The best thing you can do with your book is throw it into the shredder.
    bullschildt

    It might be an easy read, but then again, most works of fiction without any basis in the real world are designed to be an easy read.
    lol!

  10. #10
    Registered User
    Join Date
    Jan 2011
    Posts
    18
    I can answer you for your second question.

    In C, any non-zero integer is considered as true and zero as false. So In the following for loop suppose e has initial value as 5. Then as 5 is non-zero number it will be considered as true and similiarly for 4,3,2,1 but as 0 comes (which means false as i told earlier) will terminate the loop.

    Code:
     
    for(; e; e--) temp = temp * m;

  11. #11
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Quote Originally Posted by CommonTater View Post
    It may sound like a really cool optimization, but if not used with caution, it can also introduce subtle, almost untraceable bugs into a program...
    I don't think so. In the days where 'register' did what it was claimed to do, up to a maximum of two such uses as I recall, the program did in fact improve performance. If there were oddball address aliasing, the compiler would have noticed it and provided sufficient code to propagate the value into real RAM (from the register) as required. Unless you can point to specific compilers which had known bugs in this regard.

    The reference book that was referred to may be out-of-date with today's much more optimizing compilers. Perhaps the keyword 'register' has just been left over for backward compatibility... and as some have commented, its ultimate efficacy is highly questionable. It has been relegated to being a mere suggestion. The compiler can chose to ignore its use in all cases and still be C compliant.

  12. #12
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Since we're talking about history, I'm referencing the C89 standard...
    Quote Originally Posted by C89 3.5.1
    A declaration of an identifier for an object with storage-class specifier register suggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-defined. (49)
    Quote Originally Posted by nonoob View Post
    I don't think so. In the days where 'register' did what it was claimed to do, up to a maximum of two such uses as I recall, the program did in fact improve performance.
    register still "does what it's supposed to do", which is suggest the compiler make it as fast as possible. The limit of how many register variables you could use effectively was architecture dependent. The SPARC architecture used by Sun had 8 global general purpose registers and 8 local general purpose registers per frame (they had a sexy sliding-frame setup for function calls). The compiler could possibly put 16+ variables in registers.

    If there were oddball address aliasing, the compiler would have noticed it and provided sufficient code to propagate the value into real RAM (from the register) as required. Unless you can point to specific compilers which had known bugs in this regard.
    Determining the address of a register variable is expressly prohibited, which makes perfect sense since it might not be in memory and thus has no address:
    Quote Originally Posted by C89 standard footnote 49
    The implementation may treat any register declaration simply as an auto declaration. However, whether or not addressable storage is actually used, the address of any part of an object declared with storage-class specifier register may not be computed, either explicitly (by use of the unary & operator as discussed in 3.3.3.2) or implicitly (by converting an array name to a pointer as discussed in 3.2.2.1). Thus the only operator that can be applied to an array declared with storage-class specifier register is sizeof .
    As an aside, could you compile your example Tater? What compiler are you using? GCC wouldn't let me...

    The reference book that was referred to may be out-of-date with today's much more optimizing compilers. Perhaps the keyword 'register' has just been left over for backward compatibility...
    Doubtful. Compiler writers are pretty awesome coders and their optimizations are generally much faster, but not knowing the intent of your code, they can only optimize so much. It's quite possible that you have some intricate knowledge of your algorithm and know you want a specific variable in a register, thus I would wager most decent compilers do their darnedest to honor the keyword, assuming that if you use it, you know what you're doing. Indeed, GCC (v4.4.4) translated the following two declarations differently:
    Code:
    // foo.c
    #include <stdio.h>
    
    int main(void)
    {
        int x = 5;
        register int y = 10;
    	
        printf("x: %d\n", x);
        printf("y: %d\n", y);
    
        return 0;
    }
    gcc -S foo.c
    Code:
        movl    $5, 28(%esp) ; this is x, referenced from the stack pointer
        movl    $10, %ebx    ; this is y, stored directly in a register

  13. #13
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    Good reference anduril! That pretty much make it very clear. I presonally dont use the register, not that i dont want to, its just that i dont have to as the system are far much faster and better to handle communication between the processor and the memory. The last time i used the register place holder was when i was working on register specially on RTOS application wheew things need to done on time strain.

    Perhaps the OP should have got clear picture on when and when not to use register. Extensive use of register would also be penalised by the compiler as an optimisation.

    ssharish
    Life is like riding a bicycle. To keep your balance you must keep moving - Einstein

  14. #14
    Registered User
    Join Date
    Mar 2009
    Posts
    344
    Quote Originally Posted by anduril462 View Post
    Doubtful. Compiler writers are pretty awesome coders and their optimizations are generally much faster, but not knowing the intent of your code, they can only optimize so much. It's quite possible that you have some intricate knowledge of your algorithm and know you want a specific variable in a register, thus I would wager most decent compilers do their darnedest to honor the keyword, assuming that if you use it, you know what you're doing. Indeed, GCC (v4.4.4) translated the following two declarations differently:
    Code:
    // foo.c
    #include <stdio.h>
    
    int main(void)
    {
        int x = 5;
        register int y = 10;
    	
        printf("x: %d\n", x);
        printf("y: %d\n", y);
    
        return 0;
    }
    gcc -S foo.c
    Code:
        movl    $5, 28(%esp) ; this is x, referenced from the stack pointer
        movl    $10, %ebx    ; this is y, stored directly in a register
    Try this with any level of optimization and you'll see the compiler ignore the keyword. No fair testing how the compiler optimizes code with the optimizer turned off.

    Code:
    	movl	$5, 4(%esp)
    	movl	$LC0, (%esp)
    	call	_printf
    	movl	$10, 4(%esp)
    	movl	$LC1, (%esp)	 #,
    	call	_printf
    Identical treatment for x and y - both are constants pushed onto the stack before calling printf(). From what I've seen, the GCC devs say that with optimization turned on GCC ignores the keyword register. Their take seems to be that "produce the fastest code possible for this var" is "let the compiler do whatever it deems best and not let the user interfere".

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    The reasons for not using register (and for compilers to ignore you if you do) are generally:

    1. You don't have a clue how many real registers are available for use. This is especially true for any code which is designed to be cross-platform. Even if you know you're programming for an X86, you don't necessarily know how the compiler writer has chosen to allocate the available registers for special purpose or for general use.

    2. Programmers estimations of what would make a good register variable are about as reliable as programmers estimations of where the performance hot-spots are. In other words, without profiling it, pretty useless.

    3. Having carefully analysed a section of code to decide which variable would be best for register, you would have to repeat the exercise EVERY time the code was changed (in case something else would now be better as register). Is this likely to be done - not a chance. Mostly, the keyword would be sprayed like fairy dust over the code hoping for some magical effect.

    'register' was an easy win 40 years ago when C was first written, when there was only one compiler for one machine, and all code was written by a very small group of people who knew the compiler inside out.

    As soon as compilers started appearing with any kind of '-O' flags, the game was largely over for the register keyword as being something useful for improving the code.

    You only have to look at the long list of '-fopt' flags offered by GCC aimed at code optimisation to realise that it knows a hell of a lot more about how to get the best out of the code. More than could ever be achieved by some enthusiastic programmer spraying 'register' all over the code.

    The only thing you can actually be sure of is that declaring a variable as 'register' will prevent you from pointing to it.
    Code:
    register int p;
    int *pa = &p;  // this is not allowed
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed