register

Discussion in 'C Programming' started by orium69@gmail.com, Nov 9, 2005.

  1. Guest

    hi everyone, i'm wondering if there is a way to have sure that a
    variable is allocated in the cache, after its declaration with
    "register"? Tks!
     
    , Nov 9, 2005
    #1
    1. Advertising

  2. >hi everyone, i'm wondering if there is a way to have sure that a
    >variable is allocated in the cache, after its declaration with
    >"register"? Tks!


    On all processors I have ever heard of with a cache, actual CPU
    registers are never part of the cache. Actual CPU registers
    are normally much faster than the cache.

    You can never be sure that the keyword 'register' will affect
    the code at all. And if you use it enough, you *WILL* run out
    of actual CPU registers. If you could force a variable into a
    CPU register, it might slow down the code because the register
    might be better used as an invisible temporary. The compiler
    is often smarter than you are.

    Gordon L. Burditt
     
    Gordon Burditt, Nov 9, 2005
    #2
    1. Advertising

  3. Jordan Abel Guest

    On 2005-11-09, Gordon Burditt <> wrote:
    >>hi everyone, i'm wondering if there is a way to have sure that a
    >>variable is allocated in the cache, after its declaration with
    >>"register"? Tks!

    >
    > On all processors I have ever heard of with a cache, actual CPU
    > registers are never part of the cache. Actual CPU registers
    > are normally much faster than the cache.
    >
    > You can never be sure that the keyword 'register' will affect
    > the code at all. And if you use it enough, you *WILL* run out
    > of actual CPU registers. If you could force a variable into a
    > CPU register, it might slow down the code because the register
    > might be better used as an invisible temporary. The compiler
    > is often smarter than you are.


    The compiler also isn't required to listen to you. All "register" means
    is that the compiler is free to not give the variable an address. This
    could otherwise be determined by code analysis, i'm sure, but a keyword
    is simpler.
     
    Jordan Abel, Nov 9, 2005
    #3
  4. In article <>,
    <> wrote:
    >hi everyone, i'm wondering if there is a way to have sure that a
    >variable is allocated in the cache, after its declaration with
    >"register"? Tks!


    The answers you will get will all boil down to "You can't know and you
    shouldn't want to know."

    However, the bottom line is: Invoke the compiler with an option that causes
    it to output assembly (e.g., "gcc -S") and then look at the generated
    assembly. You should be able to figure out what it did with your
    "register" directive.
     
    Kenny McCormack, Nov 9, 2005
    #4
  5. On Wed, 09 Nov 2005 20:10:12 GMT, in comp.lang.c ,
    (Kenny McCormack) wrote:

    >In article <>,
    > <> wrote:
    >>hi everyone, i'm wondering if there is a way to have sure that a
    >>variable is allocated in the cache, after its declaration with
    >>"register"? Tks!

    >
    >The answers you will get will all boil down to "You can't know and you
    >shouldn't want to know."


    >However, the bottom line is: Invoke the compiler with an option that causes
    >it to output assembly (e.g., "gcc -S") and then look at the generated
    >assembly. You should be able to figure out what it did with your
    >"register" directive.


    This won't tell you a thing about how the CPU will use the cache at
    runtime. Never mind that if its in a register, it cannot be in a
    cache...

    In fact, this is a classic example of why answering offtopic questions
    here is a bad idea.
    --
    Mark McIntyre
    CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
    CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

    ----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
    http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
    ----= East and West-Coast Server Farms - Total Privacy via Encryption =----
     
    Mark McIntyre, Nov 9, 2005
    #5
  6. Alex Fraser Guest

    "Jordan Abel" <> wrote in message
    news:...
    [snip]
    > The compiler also isn't required to listen to you. All "register" means
    > is that the compiler is free to not give the variable an address.


    I would say all it means is that you cannot take the address of the object.
    What you wrote follows from that fact.

    > This could otherwise be determined by code analysis, i'm sure, but a
    > keyword is simpler.


    These days, such analysis (and then some) is certainly practical, but
    presumably it wasn't always that way, and that is why the keyword exists.

    Alex
     
    Alex Fraser, Nov 9, 2005
    #6
  7. Jordan Abel <> writes:
    > On 2005-11-09, Gordon Burditt <> wrote:
    >>>hi everyone, i'm wondering if there is a way to have sure that a
    >>>variable is allocated in the cache, after its declaration with
    >>>"register"? Tks!

    >>
    >> On all processors I have ever heard of with a cache, actual CPU
    >> registers are never part of the cache. Actual CPU registers
    >> are normally much faster than the cache.
    >>
    >> You can never be sure that the keyword 'register' will affect
    >> the code at all. And if you use it enough, you *WILL* run out
    >> of actual CPU registers. If you could force a variable into a
    >> CPU register, it might slow down the code because the register
    >> might be better used as an invisible temporary. The compiler
    >> is often smarter than you are.

    >
    > The compiler also isn't required to listen to you. All "register" means
    > is that the compiler is free to not give the variable an address. This
    > could otherwise be determined by code analysis, i'm sure, but a keyword
    > is simpler.


    Here's what the standard says, C99 6.7.1p4:

    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.

    with a footnote:

    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 cannot be computed, either
    explicitly (by use of the unary & operator as discussed in
    6.5.3.2) or implicitly (by converting an array name to a pointer
    as discussed in 6.3.2.1). Thus, the only operator that can be
    applied to an array declared with storage-class specifier register
    is sizeof.

    6.5.4.2 says you can't apply unary "&" to a register-qualified object.
    6.3.2.1 says that the implicit conversion of an array expression to a
    pointer to its first element invokes undefined behavior if the
    designated array object has register storage class. (I'm not sure why
    it's undefined behavior rather than a constraint violation.)n

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 9, 2005
    #7
  8. In article <>,
    Mark McIntyre <> wrote:
    ....
    >This won't tell you a thing about how the CPU will use the cache at
    >runtime. Never mind that if its in a register, it cannot be in a
    >cache...


    You're being needlessly pedantic - and, might I add, definitely not PC.
    I think we can assume that the OP meant "CPU register" when he said
    "cache". Remember, these dorks use terminology very loosely and generally
    just repeat words they've overheard.

    >In fact, this is a classic example of why answering offtopic questions
    >here is a bad idea.


    Sez you.
     
    Kenny McCormack, Nov 10, 2005
    #8
  9. (Kenny McCormack) writes:
    > In article <>,
    > Mark McIntyre <> wrote:
    > ...
    >>This won't tell you a thing about how the CPU will use the cache at
    >>runtime. Never mind that if its in a register, it cannot be in a
    >>cache...

    >
    > You're being needlessly pedantic - and, might I add, definitely not PC.
    > I think we can assume that the OP meant "CPU register" when he said
    > "cache".


    Perhaps, but I don't think we *need* to assume any such thing. It's
    likely that the OP didn't understand what registers and cache really
    are. If he's been following this thread, he should now have a much
    better understanding of the terms.

    (The term "cache" as a generic term is applicable to registers, but in
    this context it more commonly refers to something else.)

    I suppose we could have guessed what he meant by the term "cache" and
    pretended his usage was correct. Then we could have fooled him into
    thinking that he was getting a real answer to his question, something
    like "Just use the register keyword, it guarantees that the variable
    will be stored in cache."

    But most of us are more interested in passing on knowledge than in
    playing stupid games like that.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 10, 2005
    #9
  10. pete Guest

    Keith Thompson wrote:
    >
    > (Kenny McCormack) writes:


    > But most of us are more interested in passing on knowledge than in
    > playing stupid games like that.


    But Kenny isn't.

    http://www.codecomments.com/Unix_Programming/message665290.html

    <OT>
    Poor Kenny. The people in comp.lang.c aren't amenable to redefining
    the purpose of the newsgroup to suit him. One wonders why he continues
    to hang around there ;-)
    </OT>
    I stick around, read, and post, for the same reasons I do in
    any other joke newsgroup - because it is so much fun.

    --
    pete
     
    pete, Nov 10, 2005
    #10
  11. Richard Bos Guest

    (Gordon Burditt) wrote:

    > You can never be sure that the keyword 'register' will affect
    > the code at all. And if you use it enough, you *WILL* run out
    > of actual CPU registers.


    Erm... I spot an inconsistency.

    Richard
     
    Richard Bos, Nov 10, 2005
    #11
  12. Simon Biber Guest

    Keith Thompson wrote:
    > Jordan Abel <> writes:
    >
    >>On 2005-11-09, Gordon Burditt <> wrote:
    >>
    >>>>hi everyone, i'm wondering if there is a way to have sure that a
    >>>>variable is allocated in the cache, after its declaration with
    >>>>"register"? Tks!
    >>>
    >>>On all processors I have ever heard of with a cache, actual CPU
    >>>registers are never part of the cache. Actual CPU registers
    >>>are normally much faster than the cache.
    >>>
    >>>You can never be sure that the keyword 'register' will affect
    >>>the code at all. And if you use it enough, you *WILL* run out
    >>>of actual CPU registers. If you could force a variable into a
    >>>CPU register, it might slow down the code because the register
    >>>might be better used as an invisible temporary. The compiler
    >>>is often smarter than you are.

    >>
    >>The compiler also isn't required to listen to you. All "register" means
    >>is that the compiler is free to not give the variable an address. This
    >>could otherwise be determined by code analysis, i'm sure, but a keyword
    >>is simpler.

    >
    >
    > Here's what the standard says, C99 6.7.1p4:
    >
    > 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.
    >
    > with a footnote:
    >
    > 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 cannot be computed, either
    > explicitly (by use of the unary & operator as discussed in
    > 6.5.3.2) or implicitly (by converting an array name to a pointer
    > as discussed in 6.3.2.1). Thus, the only operator that can be
    > applied to an array declared with storage-class specifier register
    > is sizeof.
    >
    > 6.5.4.2 says you can't apply unary "&" to a register-qualified object.
    > 6.3.2.1 says that the implicit conversion of an array expression to a
    > pointer to its first element invokes undefined behavior if the
    > designated array object has register storage class. (I'm not sure why
    > it's undefined behavior rather than a constraint violation.)n
    >


    So is this code acceptable in C99?

    #include <stdio.h>

    int main(void)
    {
    register int a[2] = {
    printf("%zu\n", sizeof *a),
    printf("%zu\n", sizeof a)
    };
    return 0;
    }

    Since it's a normal array, and not a variable-length array, the
    expression *a should never be evaluated, but just the type examined to
    determine its size.

    --
    Simon.
     
    Simon Biber, Nov 10, 2005
    #12
  13. Simon Biber <> writes:
    > Keith Thompson wrote:

    [...]
    >> 6.5.4.2 says you can't apply unary "&" to a register-qualified
    >> object.
    >> 6.3.2.1 says that the implicit conversion of an array expression to a
    >> pointer to its first element invokes undefined behavior if the
    >> designated array object has register storage class. (I'm not sure why
    >> it's undefined behavior rather than a constraint violation.)n
    >>

    >
    > So is this code acceptable in C99?
    >
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > register int a[2] = {
    > printf("%zu\n", sizeof *a),
    > printf("%zu\n", sizeof a)
    > };
    > return 0;
    > }
    >
    > Since it's a normal array, and not a variable-length array, the
    > expression *a should never be evaluated, but just the type examined to
    > determine its size.


    Well, *I* certainly wouldn't accept it. :cool:}

    But yes, I believe it's legal (no constraint violations, no undefined
    behavior, but implementation-defined behavior because the output
    depends on sizeof(int)).

    <OT>
    gcc complains "error: address of register variable 'a' requested" on
    "sizeof *a". I believe gcc is wrong, but of course spurious
    diagnostics don't make an implementation non-conforming.
    </OT>

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 10, 2005
    #13
  14. Jordan Abel Guest

    On 2005-11-10, Keith Thompson <> wrote:
    > Simon Biber <> writes:
    >> Keith Thompson wrote:

    > [...]
    >>> 6.5.4.2 says you can't apply unary "&" to a register-qualified
    >>> object.
    >>> 6.3.2.1 says that the implicit conversion of an array expression to a
    >>> pointer to its first element invokes undefined behavior if the
    >>> designated array object has register storage class. (I'm not sure why
    >>> it's undefined behavior rather than a constraint violation.)n
    >>>

    >>
    >> So is this code acceptable in C99?
    >>
    >> #include <stdio.h>
    >>
    >> int main(void)
    >> {
    >> register int a[2] = {
    >> printf("%zu\n", sizeof *a),
    >> printf("%zu\n", sizeof a)
    >> };
    >> return 0;
    >> }
    >>
    >> Since it's a normal array, and not a variable-length array, the
    >> expression *a should never be evaluated, but just the type examined to
    >> determine its size.

    >
    > Well, *I* certainly wouldn't accept it. :cool:}
    >
    > But yes, I believe it's legal (no constraint violations, no undefined
    > behavior, but implementation-defined behavior because the output
    > depends on sizeof(int)).
    >
    > <OT>
    > gcc complains "error: address of register variable 'a' requested" on
    > "sizeof *a". I believe gcc is wrong, but of course spurious
    > diagnostics don't make an implementation non-conforming.


    I believe spurious _errors_ do. had it been a warning you'd be fine.
    and are you sure it's not complaining at "sizeof a"? that's the one
    where an address would be taken were the value to be used.
     
    Jordan Abel, Nov 10, 2005
    #14
  15. Skarmander Guest

    Keith Thompson wrote:
    > Simon Biber <> writes:
    >
    >>Keith Thompson wrote:

    >
    > [...]
    >
    >>>6.5.4.2 says you can't apply unary "&" to a register-qualified
    >>>object.
    >>>6.3.2.1 says that the implicit conversion of an array expression to a
    >>>pointer to its first element invokes undefined behavior if the
    >>>designated array object has register storage class. (I'm not sure why
    >>>it's undefined behavior rather than a constraint violation.)n
    >>>

    >>
    >>So is this code acceptable in C99?
    >>
    >>#include <stdio.h>
    >>
    >>int main(void)
    >>{
    >> register int a[2] = {
    >> printf("%zu\n", sizeof *a),
    >> printf("%zu\n", sizeof a)
    >> };
    >> return 0;
    >>}
    >>
    >>Since it's a normal array, and not a variable-length array, the
    >>expression *a should never be evaluated, but just the type examined to
    >>determine its size.

    >
    >
    > Well, *I* certainly wouldn't accept it. :cool:}
    >
    > But yes, I believe it's legal (no constraint violations, no undefined
    > behavior, but implementation-defined behavior because the output
    > depends on sizeof(int)).
    >
    > <OT>
    > gcc complains "error: address of register variable 'a' requested" on
    > "sizeof *a". I believe gcc is wrong, but of course spurious
    > diagnostics don't make an implementation non-conforming.
    > </OT>
    >


    I believe gcc is not wrong and that there *is* undefined behavior. I'm
    not a language lawyer, so see if you can poke holes in this.

    "Except when it is the operand of the sizeof operator or the unary &
    operator, or is a string literal used to initialize an array, an
    expression that has type "array of type" is converted to an expression
    with type "pointer to type" that points to the initial element of the
    array object and is not an lvalue. If the array object has register
    storage class, the behavior is undefined."

    Now *do not* tell me about the "except when it is the operand of the
    sizeof operator" part. I *read it*. In the expression `sizeof *a', `a'
    *is not* the operand of the sizeof operator -- `*a' is. Although `*a' is
    not evaluated, its type must be determined. In order to do that, `a'
    must be converted to a pointer (otherwise `*a' is a constraint
    violation) and this conversion invokes undefined behavior.

    Conversely, `sizeof a' is perfectly fine since here the exception
    applies: `a' is the operand of the sizeof operator and the type is known.

    S.
     
    Skarmander, Nov 10, 2005
    #15
  16. Jordan Abel <> writes:
    > On 2005-11-10, Keith Thompson <> wrote:
    >> Simon Biber <> writes:
    >>> Keith Thompson wrote:

    >> [...]
    >>>> 6.5.4.2 says you can't apply unary "&" to a register-qualified
    >>>> object.
    >>>> 6.3.2.1 says that the implicit conversion of an array expression to a
    >>>> pointer to its first element invokes undefined behavior if the
    >>>> designated array object has register storage class. (I'm not sure why
    >>>> it's undefined behavior rather than a constraint violation.)n
    >>>>
    >>>
    >>> So is this code acceptable in C99?
    >>>
    >>> #include <stdio.h>
    >>>
    >>> int main(void)
    >>> {
    >>> register int a[2] = {
    >>> printf("%zu\n", sizeof *a),
    >>> printf("%zu\n", sizeof a)
    >>> };
    >>> return 0;
    >>> }
    >>>
    >>> Since it's a normal array, and not a variable-length array, the
    >>> expression *a should never be evaluated, but just the type examined to
    >>> determine its size.

    >>
    >> Well, *I* certainly wouldn't accept it. :cool:}
    >>
    >> But yes, I believe it's legal (no constraint violations, no undefined
    >> behavior, but implementation-defined behavior because the output
    >> depends on sizeof(int)).
    >>
    >> <OT>
    >> gcc complains "error: address of register variable 'a' requested" on
    >> "sizeof *a". I believe gcc is wrong, but of course spurious
    >> diagnostics don't make an implementation non-conforming.

    >
    > I believe spurious _errors_ do. had it been a warning you'd be fine.


    Oops, my mistake. I tried it on two different platforms, with two
    different versions of gcc. On one (gcc 3.4.4 on Cygwin), it produced
    a warning; on the other (gcc 4.0.2 on Solaris 9), it produced the same
    message, but as an error rather than as a warning. I cut-and-pasted
    the output from the latter without noticing that it was different.

    > and are you sure it's not complaining at "sizeof a"? that's the one
    > where an address would be taken were the value to be used.


    Yes, I'm sure. In "sizeof a", a is an array expression, and it's not
    converted to a pointer type because it's the operand of sizeof. In
    "sizeof *a", a is the operand of the unary "*" operator, so it would
    normally be converted to a pointer -- except that the operand of
    "sizeof" isn't evaluated (unless it's a VLA). Both expressions are ok
    because of the sizeof, but for different reasons: one because the
    operand of sizeof isn't converted from array to pointer, the other
    because any operand of sizeof is not evaluated.

    And I checked the line number in the warning/error message.

    Looks like a gcc bug (but a fairly minor one IMHO).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 10, 2005
    #16
  17. Skarmander <> writes:
    > Keith Thompson wrote:
    >> Simon Biber <> writes:
    >>
    >>>Keith Thompson wrote:

    >> [...]
    >>
    >>>>6.5.4.2 says you can't apply unary "&" to a register-qualified
    >>>>object.
    >>>>6.3.2.1 says that the implicit conversion of an array expression to a
    >>>>pointer to its first element invokes undefined behavior if the
    >>>>designated array object has register storage class. (I'm not sure why
    >>>>it's undefined behavior rather than a constraint violation.)n
    >>>>
    >>>
    >>>So is this code acceptable in C99?
    >>>
    >>>#include <stdio.h>
    >>>
    >>>int main(void)
    >>>{
    >>> register int a[2] = {
    >>> printf("%zu\n", sizeof *a),
    >>> printf("%zu\n", sizeof a)
    >>> };
    >>> return 0;
    >>>}
    >>>
    >>>Since it's a normal array, and not a variable-length array, the
    >>>expression *a should never be evaluated, but just the type examined to
    >>>determine its size.

    >> Well, *I* certainly wouldn't accept it. :cool:}
    >> But yes, I believe it's legal (no constraint violations, no undefined
    >> behavior, but implementation-defined behavior because the output
    >> depends on sizeof(int)).
    >> <OT>
    >> gcc complains "error: address of register variable 'a' requested" on
    >> "sizeof *a". I believe gcc is wrong, but of course spurious
    >> diagnostics don't make an implementation non-conforming.
    >> </OT>
    >>

    >
    > I believe gcc is not wrong and that there *is* undefined behavior. I'm
    > not a language lawyer, so see if you can poke holes in this.
    >
    > "Except when it is the operand of the sizeof operator or the unary &
    > operator, or is a string literal used to initialize an array, an
    > expression that has type "array of type" is converted to an expression
    > with type "pointer to type" that points to the initial element of the
    > array object and is not an lvalue. If the array object has register
    > storage class, the behavior is undefined."
    >
    > Now *do not* tell me about the "except when it is the operand of the
    > sizeof operator" part. I *read it*. In the expression `sizeof *a', `a'
    > *is not* the operand of the sizeof operator -- `*a' is. Although `*a'
    > is not evaluated, its type must be determined. In order to do that,
    > `a' must be converted to a pointer (otherwise `*a' is a constraint
    > violation) and this conversion invokes undefined behavior.


    I don't think so. Any conversion would be part of the evaluation of
    the expression. Because the expression "*a" as a whole is not
    evaluated, the conversion doesn't take place. The compiler is (and
    must be) perfectly capable of determining the type, and therefore the
    size, of the expression without actually evaluating it.

    > Conversely, `sizeof a' is perfectly fine since here the exception
    > applies: `a' is the operand of the sizeof operator and the type is
    > known.


    Agreed.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 10, 2005
    #17
  18. On Thu, 10 Nov 2005 00:42:16 GMT, in comp.lang.c ,
    (Kenny McCormack) wrote:

    >I think we can assume that the OP meant "CPU register" when he said
    >"cache".


    Ya reckon?

    >>In fact, this is a classic example of why answering offtopic questions
    >>here is a bad idea.

    >
    >Sez you.


    Yup, Says I. All the answers given are completely incorrect.
    --
    Mark McIntyre
    CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
    CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>

    ----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
    http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
    ----= East and West-Coast Server Farms - Total Privacy via Encryption =----
     
    Mark McIntyre, Nov 10, 2005
    #18
  19. Skarmander Guest

    Keith Thompson wrote:
    > Skarmander <> writes:
    >
    >>Keith Thompson wrote:
    >>
    >>>Simon Biber <> writes:
    >>>
    >>>
    >>>>Keith Thompson wrote:
    >>>
    >>>[...]
    >>>
    >>>
    >>>>>6.5.4.2 says you can't apply unary "&" to a register-qualified
    >>>>>object.
    >>>>>6.3.2.1 says that the implicit conversion of an array expression to a
    >>>>>pointer to its first element invokes undefined behavior if the
    >>>>>designated array object has register storage class. (I'm not sure why
    >>>>>it's undefined behavior rather than a constraint violation.)n
    >>>>>
    >>>>
    >>>>So is this code acceptable in C99?
    >>>>
    >>>>#include <stdio.h>
    >>>>
    >>>>int main(void)
    >>>>{
    >>>> register int a[2] = {
    >>>> printf("%zu\n", sizeof *a),
    >>>> printf("%zu\n", sizeof a)
    >>>> };
    >>>> return 0;
    >>>>}
    >>>>
    >>>>Since it's a normal array, and not a variable-length array, the
    >>>>expression *a should never be evaluated, but just the type examined to
    >>>>determine its size.
    >>>
    >>>Well, *I* certainly wouldn't accept it. :cool:}
    >>>But yes, I believe it's legal (no constraint violations, no undefined
    >>>behavior, but implementation-defined behavior because the output
    >>>depends on sizeof(int)).
    >>><OT>
    >>>gcc complains "error: address of register variable 'a' requested" on
    >>>"sizeof *a". I believe gcc is wrong, but of course spurious
    >>>diagnostics don't make an implementation non-conforming.
    >>></OT>
    >>>

    >>I believe gcc is not wrong and that there *is* undefined behavior. I'm
    >>not a language lawyer, so see if you can poke holes in this.
    >>
    >>"Except when it is the operand of the sizeof operator or the unary &
    >>operator, or is a string literal used to initialize an array, an
    >>expression that has type "array of type" is converted to an expression
    >>with type "pointer to type" that points to the initial element of the
    >>array object and is not an lvalue. If the array object has register
    >>storage class, the behavior is undefined."
    >>
    >>Now *do not* tell me about the "except when it is the operand of the
    >>sizeof operator" part. I *read it*. In the expression `sizeof *a', `a'
    >>*is not* the operand of the sizeof operator -- `*a' is. Although `*a'
    >>is not evaluated, its type must be determined. In order to do that,
    >>`a' must be converted to a pointer (otherwise `*a' is a constraint
    >>violation) and this conversion invokes undefined behavior.

    >
    > I don't think so. Any conversion would be part of the evaluation of
    > the expression.


    This I dispute. The standard does not mark conversion as belonging
    exclusively to the evaluation process.

    > Because the expression "*a" as a whole is not evaluated, the conversion doesn't take place.


    I agree that neither `a' nor `*a' are evaluated.

    > The compiler is (and must be) perfectly capable of determining the
    > type, and therefore the size, of the expression without actually
    > evaluating it.
    >


    I would be inclined to agree with you if you pointed out the rules in
    the standard that specify what type `*a' has in this case, without
    requiring any conversion.

    The compiler can only determine the type according to the rules laid
    down for this in the standard. The only rule I can find that specifies
    what the type of `*a' is is given in 6.5.3.2.4: "[..] If the operand has
    type 'pointer to type', the result has type 'type'." The constraints
    specify that "the operand of the unary * operator shall have pointer
    type", so that this type determination always applies.

    But `a' is not of pointer type -- without conversion, `*a' is a
    constraint violation. `a' is *not* the operand of a sizeof operator but
    of an `*' operator, therefore it is converted to an `int*' per
    6.3.2.1.3, and invokes undefined behavior per the same.

    If you believe an alternate mechanism is required or supplied by the
    standard that the compiler can apply to determine the type without going
    through conversion, I'd like to know. I don't see what magically tells
    the compiler what the type of `*a' is without tripping over the
    conversion rules.

    You can try and argue that the conversion is (part of) evaluation and
    the compiler has only to *act* as if it converted for the sake of type
    calculation, but must not actually do so. This is an eminently
    reasonable approach, but it's made up out of whole cloth; the standard
    doesn't say this is how determining types can be done. We are then
    claiming the part about undefined behavior should be ignored without
    having anything in the standard to back us up on this.

    I repeat: I agree that neither `a' nor `*a' is actually evaluated, but I
    do not agree that conversion could or should only happen on evaluation,
    and I also argue that the conversion is necessary in this case. If this
    is not the intent of the standard, I think it does not clearly specify
    how the types of expressions are to be determined.

    For contrast, consider `sizeof (0 / 0)'. The type of `0 / 0' can be
    deduced by sections in the standard (namely 6.4.4.1, 6.3.1.8 and the
    lack of any special provisions on the result type in 6.5.5) without
    needing 6.5.5.5, which specifies UB for determining the result of a
    division by zero. This is irrelevant because we do not evaluate the
    expression and do not determine a result. Therefore `sizeof (0 / 0)' is
    a well-defined expression equivalent to `sizeof int'. A similarly
    careful analysis does not seem to give us any typing information for
    `*a' that doesn't involve a clause with undefined behavior.

    (We could take this to comp.std.c., it's getting rather technical.)

    S.
     
    Skarmander, Nov 10, 2005
    #19
  20. Skarmander <> writes:
    > Keith Thompson wrote:
    >> Skarmander <> writes:

    [...]
    >>>"Except when it is the operand of the sizeof operator or the unary &
    >>>operator, or is a string literal used to initialize an array, an
    >>>expression that has type "array of type" is converted to an expression
    >>>with type "pointer to type" that points to the initial element of the
    >>>array object and is not an lvalue. If the array object has register
    >>>storage class, the behavior is undefined."
    >>>
    >>>Now *do not* tell me about the "except when it is the operand of the
    >>>sizeof operator" part. I *read it*. In the expression `sizeof *a', `a'
    >>>*is not* the operand of the sizeof operator -- `*a' is. Although `*a'
    >>>is not evaluated, its type must be determined. In order to do that,
    >>>`a' must be converted to a pointer (otherwise `*a' is a constraint
    >>>violation) and this conversion invokes undefined behavior.

    >> I don't think so. Any conversion would be part of the evaluation of
    >> the expression.

    >
    > This I dispute. The standard does not mark conversion as belonging
    > exclusively to the evaluation process.


    I'm not sure I can cite anything that absolutely proves my point, but
    here are a few quotes:

    C99 6.3p1, "Conversions":

    Several operators convert operand values from one type to another
    automatically. This subclause specifies the result required from
    such an _implicit conversion), as well as those that result from a
    cast operation (an _explicit conversion_).

    C99 6.5p1, "Expressions":

    An _expression_ is a sequence of operators and operands that
    specifies computation of a value, or that designates an object or
    a function, or that generates side effects, or that performs a
    combination thereof.

    (This is a flawed definition, since there are expressions that contain
    neither operators nor operands, but that's not relevant here.)

    And, just for completeness:

    C99 6.5.3.4p2, "The sizeof operator":

    If the type of the operand is a variable length array type, the
    operand is evaluated; otherwise, the operand is not evaluated and
    the result is an integer constant.

    It seems to me from these definitions that conversions are tied very
    tightly to expressions. Conversions occur only as a result of an
    operator being applied to an operand (not quite correct, but close
    enough), which occurs as part of expression evaluation.

    Furthermore, just as a matter of common sense (dangerous, I know),
    expression evaluation happens at execution time; type determination
    must happen at compilation time.

    [snip]

    > If you believe an alternate mechanism is required or supplied by the
    > standard that the compiler can apply to determine the type without
    > going through conversion, I'd like to know. I don't see what magically
    > tells the compiler what the type of `*a' is without tripping over the
    > conversion rules.


    There's nothing magical about it. For any non-VLA expression that's
    the operand of a sizeof operator, the compiler has to go through the
    same process it does for any expression to determine the type, but
    without evaluating the expression (or rather, without generating code
    to evaluate the expression).

    > You can try and argue that the conversion is (part of) evaluation and
    > the compiler has only to *act* as if it converted for the sake of type
    > calculation, but must not actually do so. This is an eminently
    > reasonable approach, but it's made up out of whole cloth; the standard
    > doesn't say this is how determining types can be done. We are then
    > claiming the part about undefined behavior should be ignored without
    > having anything in the standard to back us up on this.


    Then how *does* the standard say the type is determined? If it has to
    carry out a run-time operation (the conversion) to determine
    compile-time information, we're in big trouble.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 11, 2005
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jay
    Replies:
    0
    Views:
    484
  2. Max
    Replies:
    1
    Views:
    2,562
    eadgbe
    Sep 4, 2003
  3. yoga
    Replies:
    1
    Views:
    501
    Ray Andraka
    Oct 11, 2003
  4. Pierre-Louis
    Replies:
    8
    Views:
    1,017
    Bob Efram
    Oct 17, 2003
  5. Morfeusz

    Register problem(long)

    Morfeusz, Dec 1, 2003, in forum: VHDL
    Replies:
    4
    Views:
    585
    Patrick Erich
    Dec 3, 2003
Loading...

Share This Page