register keyword

Discussion in 'C Programming' started by Jackie, Jul 27, 2004.

  1. Jackie

    Jackie Guest

    Hi everyone,
    Does anyone know when "register" declarations should be used and when
    "register" must not be used? If possible please give examples for both
    cases.
    Thanks
     
    Jackie, Jul 27, 2004
    #1
    1. Advertisements

  2. Jackie wrote on 27/07/04 :
    Don't use 'register'. The compiler makes it for you.
     
    Emmanuel Delahaye, Jul 27, 2004
    #2
    1. Advertisements

  3. Jackie

    Malcolm Guest

    "register" is used when you want to hint to a compiler that a variable
    should be in a hardware register for fast access.
    Nowadays compilers are so good at assigning variables to registers that you
    can seldom achieve any speed up by using "register", and may often slow
    execution down.
    register also prevents the address of a variable from being taken, so if you
    need to set a pointer to that variable you may not declare it "register".

    examples

    void foo(void)
    {
    register int i;
    int j;
    int dummy = 0;
    clock_t tick;
    clock_t tock;

    tick = clock();
    for(i=0;i<10000;i++)
    dummy *= dummy;
    tock = clock();

    printf("Register %d\n" (int) (tock - tick));

    tick = clock();
    for(j=0;i<10000;j++)
    dummy *= dummy;
    tock = clock();

    printf("vanilla %d\n", (int) tock - tick);
    }

    void cursorpos(int *x, int *y)
    {
    /* dummy position for example */
    *x = 1;
    *y = 2;
    }

    void foo(void)
    {
    register int x;
    register int y;

    /* illegal */
    cursorpos(&x, &y);

    printf("x %d y %d\n", x, y);
    }
     
    Malcolm, Jul 27, 2004
    #3
  4. Jackie

    Jackie Guest

    Hi Malcom,
    I tried the code right below this message. It doesn't prevent the variable
    "i" address from being taken. I could compile and run it under gcc. (It
    compiles with this warning "address of register variable `i' requested" but
    nothing is prevented)
    int main()
    {
    register int i = 0;
    int j = 0;
    i++;

    int * p = &i;
    int * q = &j;

    *p = 10;
    *q = 8;

    printf("i = %d\n", i);
    printf("j = %d\n", j);
    }
    OUTPUT:
    i = 10
    j = 8
     
    Jackie, Jul 27, 2004
    #4
  5. Because it's annoying as hell.
    Why not?
    Please don't top-post.

    As to your question: Your compiler is certainly allowed to produce
    whatever executable program it likes, for whatever reason it likes.
    It has kindly warned you that your source code is /not/ valid C,
    and (in this case) it has gone ahead and produced an executable
    anyway. That doesn't mean you ought to ignore the diagnostic.

    The code as written /is/ incorrect; you /cannot/ take the address
    of an object declared 'register'.

    <OT> Try 'gcc -W -Wall -ansi -pedantic -O2'; this is the command
    line I find most useful for diagnosing invalid or potentially
    ambiguous C code. ('-W -Wall' is considered overkill by some
    regulars here.) </OT>

    HTH,
    -Arthur
     
    Arthur J. O'Dwyer, Jul 27, 2004
    #5
  6. Jackie

    Jack Klein Guest

    On Tue, 27 Jul 2004 18:02:49 GMT, "Jackie"


    As Malcom said, don't top post.
    Then whatever compiled this was not a standard C compiler. It might
    be a C compiler that was not invoked in standard C mode, and so it
    allowed some non-standard compiler-specific extensions. Or it might
    be that you compiled this with a C++ compiler, where taking the
    address of a register variable happens to be legal.

    But whatever the reason, you did not compile this with a standard C
    compiler.
     
    Jack Klein, Jul 28, 2004
    #6
  7. [Actually, it was Arthur.]
    % gcc -W -Wall -ansi -pedantic -ffloat-store jackie.c
    jackie.c: In function `main':
    jackie.c:7: warning: address of register variable `i' requested
    jackie.c:7: warning: ISO C89 forbids mixed declarations and code
    jackie.c:13: warning: implicit declaration of function `printf'
    jackie.c:15: warning: control reaches end of non-void function

    % a.exe
    i = 10
    j = 8

    %

    In what way did I not invoke gcc as a conforming compiler?
    [But not supplying a prototype for printf isn't.]
    I think you've jumped the gun.
     
    Peter Nilsson, Jul 28, 2004
    #7
  8. Jackie

    Malcolm Guest

    That's a little factoid I was unaware of.
     
    Malcolm, Jul 28, 2004
    #8
  9. Jackie

    Richard Bos Guest

    Why? It's a constraint violation. It requires a diagnostic. A diagnostic
    was provided. Sounds conforming to me.

    Richard
     
    Richard Bos, Jul 28, 2004
    #9
  10. The register keyword should be used as a last resort when
    optimizing a function; and it is platform dependent as to
    whether it will be efficient or not. By the way, the
    "register" keyword is only a hint to the compiler. The
    compiler is allow to ignore your suggestion.

    Given a program fragment to sum array locations:

    #define ARRAY_SIZE 102400

    unsigned int array[ARRAY_SIZE];

    // Assume array has been filled with valid integers.
    unsigned int Array_Sum(unsigned int * p_array,
    unsigned int quantity)
    {
    unsigned int i;
    unsigned int sum = 0;

    for (i = 0; i < quantity; ++i)
    {
    sum += p_array;
    }
    return sum;
    }

    In the above function, Array_Sum, the array is
    accessed one location at a time. In generic
    computer theory, accessing many memory locations
    at once is faster than many accesses to many
    memory locations.

    Here is the same function, but applying the
    above idea and loop unrolling:
    unsigned int Array_Sum(unsigned int * p_array,
    unsigned int quantity)
    {
    unsigned int i;
    unsigned int sum = 0;

    /* declare some temporary values to use the
    processors "extra" registers */
    register unsigned int r1, r2, r3, r4;
    #define ACCESSES_PER_LOOP 4

    for (i = 0;
    i + ACCESSES_PER_LOOP < quantity;
    i += ACCESSES_PER_LOOP)
    {
    /* Read from memory into several registers */
    r1 = p_array[i + 0];
    r2 = p_array[i + 1];
    r3 = p_array[i + 2];
    r4 = p_array[i + 3];

    /* Calculate sum using registers */
    sum += r1;
    sum += r2;
    sum += r3;
    sum += r4;
    }

    /* Sum up remaining numbers */
    for (; i < quantity; ++i)
    {
    sum += p_array;
    }
    return sum;
    }

    Hopefully, the compiler is smart enough to recognize the
    reading pattern and use specialized processor instructions.
    The loop unrolling serves two purposes: 1) More data
    processing instructions are exected per branch instructions;
    and 2) Allows for multiple fetches from memory at one time.
    Whether or not the compiler or process takes advantage of
    2), depends on the compiler and the platform. This solution
    works nice on an ARM7 or ARM9 processor that has a
    special instruction for loading multiple registers from
    memory with one instruction.

    So the "register" keyword along with loop unrolling
    help form an optimization pattern. A good compiler will
    take the hints and generate appropriate code. If the
    compiler doesn't generate the optimized code, there is
    always the option of writing the code in assembly language.

    --
    Thomas Matthews

    C++ newsgroup welcome message:
    http://www.slack.net/~shiva/welcome.txt
    C++ Faq: http://www.parashift.com/c++-faq-lite
    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.learn.c-c++ faq:
    http://www.comeaucomputing.com/learn/faq/
    Other sites:
    http://www.josuttis.com -- C++ STL Library book
     
    Thomas Matthews, Jul 28, 2004
    #10
  11. But if the compiler *does* choose to place the variable into a hardware
    register, what would that address look like?
     
    Joona I Palaste, Aug 1, 2004
    #11
  12. It doesn't have to "look like" anything, it just has to work.

    For example take the code fragment

    int i, j;
    ...
    if (&i == &j) ...

    The rules of the C language imply that (&i == &j) must be zero (false).
    The compiler is free to place i or j or both into a hardware register,
    as long as it makes sure that (&i == &j) yields a value of zero.
     
    Christian Bau, Aug 1, 2004
    #12
  13. <OT>
    Most likely, if the program takes the address of a variable, the
    compiler won't choose to put that variable in a register. Either
    that, or it will mirror the value of the variable in a register and in
    a memory location, guaranteeing that the memory location holds the
    correct value whenever the address is used.
    </OT>
     
    Keith Thompson, Aug 1, 2004
    #13
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.