473,395 Members | 2,436 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

register

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 15 '05 #1
29 2438
>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
Nov 15 '05 #2
On 2005-11-09, Gordon Burditt <go***********@burditt.org> 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.
Nov 15 '05 #3
In article <11*********************@z14g2000cwz.googlegroups. com>,
<or*****@gmail.com> 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.

Nov 15 '05 #4
On Wed, 09 Nov 2005 20:10:12 GMT, in comp.lang.c ,
ga*****@yin.interaccess.com (Kenny McCormack) wrote:
In article <11*********************@z14g2000cwz.googlegroups. com>,
<or*****@gmail.com> 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 =----
Nov 15 '05 #5
"Jordan Abel" <jm****@purdue.edu> wrote in message
news:sl*******************@random.yi.org...
[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
Nov 15 '05 #6
Jordan Abel <jm****@purdue.edu> writes:
On 2005-11-09, Gordon Burditt <go***********@burditt.org> 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) ks***@mib.org <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.
Nov 15 '05 #7
In article <mb********************************@4ax.com>,
Mark McIntyre <ma**********@spamcop.net> 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.

Nov 15 '05 #8
ga*****@yin.interaccess.com (Kenny McCormack) writes:
In article <mb********************************@4ax.com>,
Mark McIntyre <ma**********@spamcop.net> 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) ks***@mib.org <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.
Nov 15 '05 #9
Keith Thompson wrote:

ga*****@yin.interaccess.com (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_Pro...age665290.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
Nov 15 '05 #10
go***********@burditt.org (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
Nov 15 '05 #11
Keith Thompson wrote:
Jordan Abel <jm****@purdue.edu> writes:
On 2005-11-09, Gordon Burditt <go***********@burditt.org> 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.
Nov 15 '05 #12
Simon Biber <ne**@ralmin.cc> 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. 8-)}

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) ks***@mib.org <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.
Nov 15 '05 #13
On 2005-11-10, Keith Thompson <ks***@mib.org> wrote:
Simon Biber <ne**@ralmin.cc> 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. 8-)}

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.
Nov 15 '05 #14
Keith Thompson wrote:
Simon Biber <ne**@ralmin.cc> 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. 8-)}

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.
Nov 15 '05 #15
Jordan Abel <jm****@purdue.edu> writes:
On 2005-11-10, Keith Thompson <ks***@mib.org> wrote:
Simon Biber <ne**@ralmin.cc> 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. 8-)}

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) ks***@mib.org <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.
Nov 15 '05 #16
Skarmander <in*****@dontmailme.com> writes:
Keith Thompson wrote:
Simon Biber <ne**@ralmin.cc> 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. 8-)}
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) ks***@mib.org <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.
Nov 15 '05 #17
On Thu, 10 Nov 2005 00:42:16 GMT, in comp.lang.c ,
ga*****@yin.interaccess.com (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 =----
Nov 15 '05 #18
Keith Thompson wrote:
Skarmander <in*****@dontmailme.com> writes:
Keith Thompson wrote:
Simon Biber <ne**@ralmin.cc> 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. 8-)}
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.
Nov 15 '05 #19
Skarmander <in*****@dontmailme.com> writes:
Keith Thompson wrote:
Skarmander <in*****@dontmailme.com> 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) ks***@mib.org <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.
Nov 15 '05 #20
Keith Thompson <ks***@mib.org> writes:
Simon Biber <ne**@ralmin.cc> 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. 8-)}

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, [...]
</OT>

The gcc error is consistent with another reading that I think is
reasonable. Here's 6.3.2.1 p3 again:

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.

I read the last sentence as saying the behavior of the _expression_ is
undefined, not that the behavior of the _conversion_ is undefined. If
read this way, the behavior should be undefined whether the expression
is evaluated or not.

Incidentally, making the behavior undefined rather than making it a
constraint violation allows an implementation to define indexing of
register arrays with so it works just like regular indexing.
Nov 15 '05 #21
Keith Thompson wrote:
Skarmander <in*****@dontmailme.com> writes:
Keith Thompson wrote:
Skarmander <in*****@dontmailme.com> writes: [tentative quotes tying conversion to evaluation]
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.

Let's say we agree on this. We can, because I can still highlight the
problem even if we assume the actual conversion is not taking place.
I'll argue that in this case, you're just stuck and have to fudge your
way out, when the standard does not require you to.
Furthermore, just as a matter of common sense (dangerous, I know),
expression evaluation happens at execution time; type determination
must happen at compilation time.

That doesn't really matter here: I already agreed evaluation is not
taking place.

That said, common sense is only half right (not bad for common sense,
but still). Constant expressions can (must not, but may) be evaluated at
compile time (6.6.2), and they're not evaluated any differently from
non-constant expressions (6.6.11).

Case in point: the very sizeof expression we've been discussing is
evaluated at compile time. This is not relevant since the discussion is
about the operand of sizeof, not the sizeof expression as a whole, but
it's fun to note. :-)

Type determination must, for the most part, happen at compilation time,
because the compiler must issue diagnostics for constraint violations,
and most of these simply require accurate typing information. (There is
probably nothing in the standard that disallows run-time typing where
constraints would not be violated, but such a hybrid implementation
would be unattractive for obvious reasons.)
[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 say that as if the undefined behavior that results from converting a
register array to a pointer is part of the code that would be generated
to evaluate the expression. It is not, or rather, nothing in the
standard says it is.
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?


By such phrases as "the type of <expression> is <type>", in particular
"The unary * operator denotes indirection. [...] If the operand has type
'pointer to type', the result has type 'type'." Note that evaluation of
the operand is not required, we need only know its type. By recursively
applying such rules, we can determine the type without even any
reference to evaluation. The sentence that immediately follows it, for
example, "If an invalid value has been assigned to the pointer, the
behavior of the unary * operator is undefined", is irrelevant: behavior
of the operator has no bearing on the typing.

I'll quote and simplify the actual case to demonstrate what I mean.

void f() {
register size_t a[1] = {sizeof *a};
}

According to both of us and the standard, `*a' is not evaluated. In my
view, the *only* rule in the *entire* standard that allows us to
determine the type of `*a' (which sizeof needs) is the one that
describes the indirection operator, quoted above. For this, `a' must be
of meta-type 'pointer to <t>', for some type t. But it is not.

By your view, we are now stuck as far as the rules we're given go. We
can't actually convert `a' to a `size_t *' because conversion is part of
evaluation, which we don't do, since we're in a sizeof. So, if I get you
correctly, you propose that the compiler now proceeds *as if* it
converted `a' to a `size_t *', concludes that the type of `*a' is
therefore `size_t', and applies sizeof accordingly.

This is *almost* my view, but with one crucial difference. I propose
this must follow 6.3.2.1.3 exactly: "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."

Here is the essence of the problem: even if we agree that the compiler
does not actually need to *do* anything to yield "an expression [...]
that points to the initial element of the array object and is not an
lvalue" because it only needs the go-ahead for the type conversion, we
*still* trigger the UB clause.

We *know* at compile time that `a' has register storage class, and there
is no other way of completing the typing process. We must follow these
rules because no others will get the job done, and they say we've messed
up and the compiler may unleash the nasal demons. Nothing in the
standard says "because you're not evaluating `a', you may pretend there
is no UB" or "because you're not evaluating `a', you may make up your
own rules about the typing that resemble the ones used when evaluating".
If it has to carry out a run-time operation (the conversion) to
determine compile-time information, we're in big trouble.


Where does it say conversion *of this kind* is a run-time operation? We
would be in big trouble if we found out we needed conversions of *actual
values* to do typing, but we don't. But at this point we simply *need*
to apply at least that part of the conversion that includes the typing
rules, and it comes with UB.

S.
Nov 15 '05 #22
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:43****************@news.xs4all.nl...
go***********@burditt.org (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.


So say what it is. Why make us guess?

He is saying the "register" is not *always* used, as such, by the CPU,
but on the converse, by using it too much, you fill up registers that
can be used, by taking away the CPU's decision making process, thus
making less registers available, thus causing other "register" variables
to not be register variables.

Seems quite clear to me.

--
Mabden
Nov 15 '05 #23
Mabden wrote:

"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:43****************@news.xs4all.nl...
go***********@burditt.org (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.


So say what it is. Why make us guess?

He is saying the "register" is not *always* used, as such, by the CPU,
but on the converse, by using it too much, you fill up registers that
can be used, by taking away the CPU's decision making process, thus
making less registers available,
thus causing other "register" variables
to not be register variables.

Seems quite clear to me.


He's using a circular definition of "enough".
If you wish hard enough,
all of your pennies *WILL* turn into gold.
You're using "too much" the same way.

--
pete
Nov 15 '05 #24
"pete" <pf*****@mindspring.com> wrote in message
news:43***********@mindspring.com...
Mabden wrote:

"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:43****************@news.xs4all.nl...
go***********@burditt.org (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.


So say what it is. Why make us guess?

He is saying the "register" is not *always* used, as such, by the CPU, but on the converse, by using it too much, you fill up registers that can be used, by taking away the CPU's decision making process, thus
making less registers available,
thus causing other "register" variables
to not be register variables.

Seems quite clear to me.


He's using a circular definition of "enough".
If you wish hard enough,
all of your pennies *WILL* turn into gold.
You're using "too much" the same way.


Ok, that helped. How?

--
Mabden
Nov 15 '05 #25
In article <43***********@mindspring.com>,
pete <pf*****@mindspring.com> wrote:
....
But Kenny isn't.

http://www.codecomments.com/Unix_Pro...age665290.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.


Thank you for posting taking the time to find and post that. Saves me the
trouble. It makes my case very well, but I really don't see how you could
think that it furthers your case. Except that, what I really think some of
you believe is that it is morally wrong to have fun here. It is as if
someone was having fun in church - which is, of course, a very apt analogy.

I'm clear about why I read and post in this joke newsgroup, but I really
don't see why some of you do. What needs of yours are being met?

Nov 15 '05 #26
ga*****@yin.interaccess.com (Kenny McCormack) writes:
[the usual crap]

Kenny: Please go away and have your "fun" somewhere else.

Everyone else:

___________________
/| /| | |
||__|| | Please do |
/ O O\__ NOT |
/ \ feed the |
/ \ \ trolls |
/ _ \ \ ______________|
/ |\____\ \ ||
/ | | | |\____/ ||
/ \|_|_|/ \ __||
/ / \ |____| ||
/ | | /| | --|
| | |// |____ --|
* _ | |_|_|_| | \-/
*-- _--\ _ \ // |
/ _ \\ _ // | /
* / \_ /- | - | |
* ___ c_c_c_C/ \C_c_c_c____________
--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 15 '05 #27
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
ga*****@yin.interaccess.com (Kenny McCormack) writes:
[the usual crap]

Kenny: Please go away and have your "fun" somewhere else.
It's too much fun here. Sorry if that offends you (having fun in church,
you know...)
Everyone else:

___________________


Made ya look!

Nov 15 '05 #28
"Mabden" <mabden@sbc_global.net> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:43****************@news.xs4all.nl...
go***********@burditt.org (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.


So say what it is. Why make us guess?


If you can't be sure that "register" has any effect at all, you cannot
know that you _will_ run out of anything, including registers. If you
know that you will eventually run out of registers, that in itself is a
way in which "register" will affect your code.

(The first of Gordon's sentences is true. The last one is not. It used
to be true, but modern compilers are much better at optimising.)

Richard
Nov 15 '05 #29
Richard Bos wrote:
"Mabden" <mabden@sbc_global.net> wrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:43****************@news.xs4all.nl...
go***********@burditt.org (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.


So say what it is. Why make us guess?


If you can't be sure that "register" has any effect at all, you cannot
know that you _will_ run out of anything, including registers. If you
know that you will eventually run out of registers, that in itself is a
way in which "register" will affect your code.

(The first of Gordon's sentences is true. The last one is not. It used
to be true, but modern compilers are much better at optimising.)


In the desktop world, yes. For embedded systems, most bets are off.

For some target platforms, it seems more important that the vendors
whip out some sort of compiler in short time than a good one in
appropriate time. If it is halfway conforming and does not blunder at
the most elementary stuff, then everything is fine.
Some code generators even "code around" the known compiler bugs and
inefficiencies by default as there are enough of both to justify
the additional effort.

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 15 '05 #30

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: G Kannan | last post by:
Hey all! I have written a perl script to retrieve information from a HTML Form and insert the data into an Oracle database table. I am gettting the the following error message: "Use of...
12
by: Ioannis Vranos | last post by:
Just some thought on it, wanting to see any explanations. It was advised in this newsgroups that we should avoid the use of keyword register. However it is a language feature, and if it...
3
by: Alex | last post by:
I apoligise in advance if this is an os or platform based question, I don't know. I was wondering how register integers (and other types of register variables) are managed by c++. For example,...
14
by: aruna | last post by:
What is the disadvantage of using register storage class specifier?
9
by: Jackie | last post by:
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
33
by: Snis Pilbor | last post by:
With the "as if" rule in play, doesn't that effectively render the "register" keyword completely useless? Example: I make a silly compiler which creates code that goes out of its way to take a...
5
by: prouleau001 | last post by:
Hi all! Since that the decorator syntax is upon us, I think it would be good if atexit.register() was returning the function passed as argument. This simple change to the library would solve a...
26
by: Vashna | last post by:
Hi Group, I have a doubt about register variables. I know that if we have a variable used very frequently in a function, then provided we never apply the & function to it, we can define it as...
21
by: JOYCE | last post by:
Look the subject,that's my problem! I hope someone can help me, thanks
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.