468,463 Members | 2,026 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,463 developers. It's quick & easy.

Left shift

Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"

Why? And how can I get rid of that?

Thank you.
Chris
Aug 23 '06 #1
56 14434

Christian Christmann wrote:
Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"

Why?
Because your implementation's representation of int is apparently < 33
bits.
And how can I get rid of that?
You could try:

static_cast<int>((1L << 32) - 1);

This will work if int is 32 bits.

Aug 23 '06 #2
Christian Christmann posted:
Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"

Why? And how can I get rid of that?

You're either trying to do one of two things:

(1) Set a to 4294967295

(2) Set all bits to zero except the sign bit, then subtract 1. This will have
a different effect on different systems.

--

Frederick Gotham
Aug 23 '06 #3

"Noah Roberts" <ro**********@gmail.comwrote in message
news:11**********************@m73g2000cwd.googlegr oups.com...
>
Christian Christmann wrote:
>Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"

Why?

Because your implementation's representation of int is apparently < 33
bits.
>And how can I get rid of that?

You could try:

static_cast<int>((1L << 32) - 1);

This will work if int is 32 bits.
Or, since you're just setting those 32 bits to 1s, you could use:

static const int a = 0xffffffff;

-Howard

Aug 23 '06 #4
Christian Christmann <pl*****@yahoo.dewrote:
Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"

Why? And how can I get rid of that?
You can only shift by (n-1), where n is the number of bits in the type.
For example, suppose an int is 8 bits. Then

1 << 0 == 00000001
1 << 1 == 00000010
1 << 2 == 00000100
1 << 3 == 00001000
1 << 4 == 00010000
1 << 5 == 00100000
1 << 6 == 01000000
1 << 7 == 10000000

At this point, since an int is 8 bits, we can see why we can only shift
a maximum of 7. When it gets to (1 << 8), what should it do? Shift the
1 completely out of the number? Or leave it where it is? I'm not sure
but this is probably one of {undefined, unspecified,
implementation-defined}.

In your case, an int must be 32 bits or smaller, but you are trying to
shift it by 32 places.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Aug 23 '06 #5

Christian Christmann wrote:
Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"
Seems like a relatively lucid warning to me.
Why?
Because on your system, the number of bits in an int is less than or
equal to 32. And that means that, on your system, (1 << 32) is equal
to 0. Think about it - if you shift a 1 from the first bit to the 33rd
bit, but there are only 32 bits, what are you left with? So "a" in
your example is equal to -1, which I'm guessing is not what you
intended.
And how can I get rid of that?
Uhhm, shift fewer than 32 times and use an unsigned int? What is it
you're trying to do?

Best regards,

Tom

Aug 23 '06 #6
On 23 Aug 2006 09:58:13 -0700, "Noah Roberts" <ro**********@gmail.com>
wrote in comp.lang.c++:
>
Christian Christmann wrote:
Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"

Why?

Because your implementation's representation of int is apparently < 33
bits.
And how can I get rid of that?

You could try:

static_cast<int>((1L << 32) - 1);

This will work if int is 32 bits.
Only if long has more than 32 bits.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Aug 24 '06 #7
Thomas Tutone wrote:
Christian Christmann wrote:
Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"

Seems like a relatively lucid warning to me.
Why?

Because on your system, the number of bits in an int is less than or
equal to 32. And that means that, on your system, (1 << 32) is equal
to 0.
No. Why would it? The most trivial example why it won't is because the
actual CPU has 32 bits and a built-in instruction for << that takes
just 5
bits. On such systems, A<<N == A<<(N%32) because all higher bits
are simply ignored. On such systems 1<<32 == 1. Or the CPU may just
decide to abort the program because it's buggy.

HTH,
Michiel Salters

Aug 24 '06 #8
Mi*************@tomtom.com wrote:
Thomas Tutone wrote:
>Christian Christmann wrote:
>>Hi,

in the header of my class I've a constant

static const int a = ( 1 << 32 ) - 1;

When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"

Seems like a relatively lucid warning to me.
>>Why?

Because on your system, the number of bits in an int is less than or
equal to 32. And that means that, on your system, (1 << 32) is equal
to 0.

No. Why would it? The most trivial example why it won't is because the
actual CPU has 32 bits and a built-in instruction for << that takes
just 5
bits. On such systems, A<<N == A<<(N%32) because all higher bits
are simply ignored. On such systems 1<<32 == 1. Or the CPU may just
decide to abort the program because it's buggy.
Whatever conclusions you're trying to make from whatever knowledge you
possess about the hardware are nonconsequential; the Standard says that
the behaviour of the program in which the right operand of the shift
operator is negative or greater than or equal to the length in bits of
the promoted left operand is *undefined*. It can be 0, it can be 1, or
(and you know the drill, repeat after me) it can make demons fly out of
your nose.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 24 '06 #9
<Mi*************@tomtom.comwrote:
>Thomas Tutone wrote:
>Christian Christmann wrote:
>>static const int a = ( 1 << 32 ) - 1;
>>When compiling the code, g++ issues the warning
"warning: left shift count >= width of type"
>Because on your system, the number of bits in an int is less than or
equal to 32. And that means that, on your system, (1 << 32) is equal
to 0.
>No. Why would it? The most trivial example why it won't is because the
actual CPU has 32 bits and a built-in instruction for << that takes
just 5 bits. On such systems, A<<N == A<<(N%32) because all higher bits
are simply ignored. On such systems 1<<32 == 1. Or the CPU may just
decide to abort the program because it's buggy.
Also I don't think there's any rule requiring the compiler
to reduce this constant expression in exactly the same manner
that the target machine would. In the above, no left shift
instruction is ever generated in the code.

Steve
Aug 25 '06 #10

Victor Bazarov wrote:
Whatever conclusions you're trying to make from whatever knowledge you
possess about the hardware are nonconsequential; the Standard says that
the behaviour of the program in which the right operand of the shift
operator is negative or greater than or equal to the length in bits of
the promoted left operand is *undefined*. It can be 0, it can be 1, or
(and you know the drill, repeat after me) it can make demons fly out of
your nose.
Is the behaviour also undefined if you shifted by 1 bit 32 times? Are
the two equivalent?

In that case ((1 << 16) << 16) would be fully defined as long as
sizeof(int) 16.

I assume, by the way, that it is perfectly defined behaviour to
right-shift bits off the end because that I do regularly, eg
right-shift 0x1234 >8 should give me 0x12. (If you're not allowed to
do that there is something horribly wrong with the standard).

Aug 25 '06 #11
Earl Purple wrote:
Victor Bazarov wrote:
>Whatever conclusions you're trying to make from whatever knowledge
you possess about the hardware are nonconsequential; the Standard
says that the behaviour of the program in which the right operand of
the shift operator is negative or greater than or equal to the
length in bits of the promoted left operand is *undefined*. It can
be 0, it can be 1, or (and you know the drill, repeat after me) it
can make demons fly out of your nose.

Is the behaviour also undefined if you shifted by 1 bit 32 times? Are
the two equivalent?
No, they are not equivalent. Shifting by 1 bit is well-defined. No
matter how many times you do it.
In that case ((1 << 16) << 16) would be fully defined as long as
sizeof(int) 16.
Correct.
I assume, by the way, that it is perfectly defined behaviour to
right-shift bits off the end because that I do regularly, eg
right-shift 0x1234 >8 should give me 0x12. (If you're not allowed to
do that there is something horribly wrong with the standard).
It's well-defined. Get a copy of the Standard to check.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 25 '06 #12

"Earl Purple" <ea********@gmail.comskrev i meddelandet
news:11**********************@i3g2000cwc.googlegro ups.com...
>
Victor Bazarov wrote:
>Whatever conclusions you're trying to make from whatever knowledge
you
possess about the hardware are nonconsequential; the Standard says
that
the behaviour of the program in which the right operand of the
shift
operator is negative or greater than or equal to the length in bits
of
the promoted left operand is *undefined*. It can be 0, it can be
1, or
(and you know the drill, repeat after me) it can make demons fly
out of
your nose.

Is the behaviour also undefined if you shifted by 1 bit 32 times?
Are
the two equivalent?

In that case ((1 << 16) << 16) would be fully defined as long as
sizeof(int) 16.
The restriction in the standard is there because of the underlying
hardware.

We expect the compiler to be able to use the shift instructions of the
CPU. The problem is that some hardware will actually perform the long
shift (with a zero result), while others will do it modulo register
size. Others might refuse altogether.

With the popular x86 family, the behaviour has changed between
generations, which makes it hard for the compiler to compensate.

So, the C++ standard says that a shift works as expected as long as
the shift count is smaller than the integer type. If it is larger we
don't know, that's up to the underlying hardware.
Bo Persson
Aug 25 '06 #13
Marcus Kwok wrote:
>
At this point, since an int is 8 bits, we can see why we can only shift
a maximum of 7. When it gets to (1 << 8), what should it do? Shift the
1 completely out of the number? Or leave it where it is? I'm not sure
but this is probably one of {undefined, unspecified,
implementation-defined}.
Undefined behavior. On the Intel i860, there is only enough bits
in the shift instruction to encode 31 places. If you do 32, it
only stuffs the low order bits and you get NOTHING. Believe me
the @&$@ X11 Server code relied on that yielding a zero not the
original operand. Had to fix it in a dozen places.

Aug 26 '06 #14
In article <44***********************@news.newshosting.com> ,
ro*@spamcop.net says...

[ ... ]
Undefined behavior. On the Intel i860, there is only enough bits
in the shift instruction to encode 31 places. If you do 32, it
only stuffs the low order bits and you get NOTHING. Believe me
the @&$@ X11 Server code relied on that yielding a zero not the
original operand. Had to fix it in a dozen places.
The x86 allows you to encode more if you want to, but recent iterations
of the processor mask it to 5 bits before doing the shift.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 26 '06 #15
Jerry Coffin <jc*****@taeus.comwrote:
>ro*@spamcop.net says...
>Undefined behavior. On the Intel i860, there is only enough bits
in the shift instruction to encode 31 places. If you do 32, it
only stuffs the low order bits and you get NOTHING. Believe me
the @&$@ X11 Server code relied on that yielding a zero not the
original operand. Had to fix it in a dozen places.
>The x86 allows you to encode more if you want to, but recent iterations
of the processor mask it to 5 bits before doing the shift.
And I still say for in the code fragment posted, no left shift
instruction will ever be emitted by the compiler, so such details are
quite possibly irrelevant.

Steve
Aug 26 '06 #16
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...

[ ... ]
And I still say for in the code fragment posted, no left shift
instruction will ever be emitted by the compiler, so such details are
quite possibly irrelevant.
This seems almost self-contradictory. If you could be certain the
compiler wouldn't emit a left-shift instruction, then such details would
be definitely irrelevant. The only way they may be relevant is if the
compiler might emit the instruction -- which I'd say is correct for at
least a few compilers.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 26 '06 #17
Jerry Coffin <jc*****@taeus.comwrote:
sp*****@speedymail.org says...
>And I still say for in the code fragment posted, no left shift
instruction will ever be emitted by the compiler, so such details are
quite possibly irrelevant.
This seems almost self-contradictory. If you could be certain
the compiler wouldn't emit a left-shift instruction, then such
details would be definitely irrelevant. The only way they may
be relevant is if the compiler might emit the instruction --
which I'd say is correct for at least a few compilers.
That is why I said "possibly irrelevant". "Intuitively, constant
expressions are simple expressions that can be evaluated by the
compiler before the program is linked [9.1] and starts to run."
(Stroustrap, C.5) To me it's unintuitive (but not incorrect) that
the compiler would not reduce the expression.

And actually, if the constant expression reduces to zero and is
assigned to a pointer, it's probably incorrect for the compiler
not to reduce it; but maybe those more expert than I might have
an opinion on this.

Steve
Aug 26 '06 #18
Following up to myself:

Steve Pope <sp*****@speedymail.orgwrote:
>Jerry Coffin <jc*****@taeus.comwrote:
>sp*****@speedymail.org says...
>>And I still say for in the code fragment posted, no left shift
instruction will ever be emitted by the compiler [..]
>This seems almost self-contradictory. If you could be certain
the compiler wouldn't emit a left-shift instruction, then such
details would be definitely irrelevant. The only way they may
be relevant is if the compiler might emit the instruction --
which I'd say is correct for at least a few compilers.
>That is why I said "possibly irrelevant". "Intuitively, constant
expressions are simple expressions that can be evaluated by the
compiler before the program is linked [9.1] and starts to run."
(Stroustrap, C.5) To me it's unintuitive (but not incorrect) that
the compiler would not reduce the expression.
>And actually, if the constant expression reduces to zero and is
assigned to a pointer, it's probably incorrect for the compiler
not to reduce it; but maybe those more expert than I might have
an opinion on this.
In fact, the following compiles (gcc):

int foo() {
int *pi;
pi = 1 << 100;
}

It seems to me that any approach that did not perform the
left shift until runtime would not be a correct implementation.

(Although there are some screwy possibilties, such as only
reducing the constant expression at compile time when it's
being assigned to a pointer; or reducing if it reduces to zero,
and issuing code for it otherwise; but I think these possibilities
are very highly remote.)

Steve
Aug 27 '06 #19

"Steve Pope" <sp*****@speedymail.orgskrev i meddelandet
news:ec**********@blue.rahul.net...
Jerry Coffin <jc*****@taeus.comwrote:
>sp*****@speedymail.org says...
>>And I still say for in the code fragment posted, no left shift
instruction will ever be emitted by the compiler, so such details
are
quite possibly irrelevant.
>This seems almost self-contradictory. If you could be certain
the compiler wouldn't emit a left-shift instruction, then such
details would be definitely irrelevant. The only way they may
be relevant is if the compiler might emit the instruction --
which I'd say is correct for at least a few compilers.

That is why I said "possibly irrelevant". "Intuitively, constant
expressions are simple expressions that can be evaluated by the
compiler before the program is linked [9.1] and starts to run."
(Stroustrap, C.5) To me it's unintuitive (but not incorrect) that
the compiler would not reduce the expression.

And actually, if the constant expression reduces to zero and is
assigned to a pointer, it's probably incorrect for the compiler
not to reduce it; but maybe those more expert than I might have
an opinion on this.
Do you mean that compile time constant expressions should be evaluated
differently than non-constant expressions? Shouldn't we expect the
same result?
To be more technical, the standard doesn't talk about compilers at
all - we could very well have an interpreter, or some other kind of
translator. And *if* a compiler does a compile time evaluation, is it
not supposed to use the hardware instructions itself, internally?
Bo Persson


Aug 27 '06 #20
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...

[ ... ]
In fact, the following compiles (gcc):

int foo() {
int *pi;
pi = 1 << 100;
}

It seems to me that any approach that did not perform the
left shift until runtime would not be a correct implementation.
I'm rather lost as to how you figure that. It's undefined behavior. How
can _any_ implementation of it be incorrect?

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 27 '06 #21
Jerry Coffin <jc*****@taeus.comwrote:
>It seems to me that any approach that did not perform the
left shift until runtime would not be a correct implementation.
I'm rather lost as to how you figure that. It's undefined
behavior. How can _any_ implementation of it be incorrect?
Here's my opinion: a correct implementation must reduce constant zero
expressions assigned to pointers at compile time.

I don't have the standard in front of me but this seems pretty
clear from Stroustrup.

Steve
Aug 27 '06 #22
Bo Persson <bo*@gmb.dkwrote:
>"Steve Pope" <sp*****@speedymail.orgskrev i meddelandet
>And actually, if the constant expression reduces to zero and is
assigned to a pointer, it's probably incorrect for the compiler
not to reduce it; but maybe those more expert than I might have
an opinion on this.
>Do you mean that compile time constant expressions should be evaluated
differently than non-constant expressions? Shouldn't we expect the
same result?
A compile-time constant expression of value zero and type integer
can be assigned to a pointer, but a variable expression of
the same type and value cannot, so yes there's a language difference.

Steve
Aug 27 '06 #23
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...
Jerry Coffin <jc*****@taeus.comwrote:
It seems to me that any approach that did not perform the
left shift until runtime would not be a correct implementation.
I'm rather lost as to how you figure that. It's undefined
behavior. How can _any_ implementation of it be incorrect?

Here's my opinion: a correct implementation must reduce constant zero
expressions assigned to pointers at compile time.
There are constant expressions, and there are some specific requirements
on those expressions. Among others, when the value of such an expression
is zero, the expression must be convertible to a pointer and result in a
null pointer.

Since you didn't quote it, I'll note that the expression being discussed
is "1<<100", and we're assuming that it's on an implementation in which
type int has 100 or fewer bits.

That's entirely irrelevant though, because the expression in question is
NOT a constant expression with a value of zero -- it's an expression
with undefined behavior. I've already pointed that out in what you've
quoted above. Maybe you don't believe that. In that case, here's what
the standard says (section 5.8/1) [expr.shift]:

The behavior is undefined if the right operand is negative,
or greater than or equal to the length in bits of the
promoted left operand.

In case you don't undertand what undefined behavior means (from section
1.3.12):

behavior, such as might arise upon use of an erroneous
program construct or erroneous data, for which this
International Standard imposes no requirements.

The standard places NO REQUIREMENT on the result of the expression in
question. Please see:

http://dialspace.dial.pipex.com/prod...een/gfd34/art/

and click on "bloopers" for information about roughly what you should
expect when you depend on undefined behavior.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 27 '06 #24
Jerry Coffin <jc*****@taeus.comwrote:
sp*****@speedymail.org says...
>Here's my opinion: a correct implementation must reduce constant zero
expressions assigned to pointers at compile time.
There are constant expressions, and there are some specific
requirements on those expressions. Among others, when the
value of such an expression is zero, the expression must be
convertible to a pointer and result in a null pointer.
Since you didn't quote it, I'll note that the expression
being discussed is "1<<100", and we're assuming that it's on
an implementation in which type int has 100 or fewer bits.
That's entirely irrelevant though, because the expression
in question is NOT a constant expression with a value of zero
-- it's an expression with undefined behavior. I've already
pointed that out in what you've quoted above. Maybe you don't
believe that.
You're drifting sideways on this, I believe.

Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
If this is true, and I think it is, then it is still true whether
or not the result of that evaluation is undefined.
In case you don't undertand what undefined behavior means
Are you trying to dodge the question here, or what?

Steve
Aug 27 '06 #25
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...

[ ... ]
You're drifting sideways on this, I believe.
You believe incorrectly.
Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
No, it does not have to be evaluated at compile time. That is not a
requirement and never has been.

You're grossly misinterpreting things -- the restrictions on constant
expressions ALLOW them to be evaluated at compile time. You're taking
that allowance and attempting to treat it as a requirement, which is
simpy wrong.
If this is true, and I think it is, then it is still true whether
or not the result of that evaluation is undefined.
First, it's not true under any circumstances. Second, even if it was
true under some other circumstances, it still wouldn't be true in the
case of undefined behavior. The standard is very clear -- any case of
undefined behavior bypasses everything else and immediately removes all
requirements of all kinds.
In case you don't undertand what undefined behavior means

Are you trying to dodge the question here, or what?
I only see one question here: how can anybody possibly read "no
requirements" as meaning "there are some requirements anyway"? I'm not
the one dodging the question; I'm the one asking it!

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 27 '06 #26
Jerry Coffin wrote:
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...
>Jerry Coffin <jc*****@taeus.comwrote:
>It seems to me that any approach that did not perform the
left shift until runtime would not be a correct implementation.
I'm rather lost as to how you figure that. It's undefined
behavior. How can _any_ implementation of it be incorrect?

Here's my opinion: a correct implementation must reduce constant zero
expressions assigned to pointers at compile time.

There are constant expressions, and there are some specific requirements
on those expressions. Among others, when the value of such an expression
is zero, the expression must be convertible to a pointer and result in a
null pointer.

Since you didn't quote it, I'll note that the expression being discussed
is "1<<100", and we're assuming that it's on an implementation in which
type int has 100 or fewer bits.

That's entirely irrelevant though, because the expression in question is
NOT a constant expression with a value of zero -- it's an expression
with undefined behavior. I've already pointed that out in what you've
quoted above. Maybe you don't believe that. In that case, here's what
the standard says (section 5.8/1) [expr.shift]:

The behavior is undefined if the right operand is negative,
or greater than or equal to the length in bits of the
promoted left operand.
I tend to disagree: the code snippet in question is:

int foo() {
int *pi;
pi = 1 << 100;
}

The assignment pi = 1 << 100 requires the right hand side to be a null
pointer constant, i.e., "an integral constant expression (5.19) rvalue of
integer type that evaluates to zero" [4.10/1]. Since an integral constant
expression is required in the statement, [3.2/2] applies, telling us that
this expression is *not* potentially evaluated. This implies that the
abstract machine is not involved. Instead the compiler is supposed to
magically know the value of the expression.

Also, notice that 1 << 100 by itself is a constant integral expression,
whence [5/5] applies:

If during the evaluation of an expression, the result is not
mathematically defined or not in the range of representable values for its
type, the behavior is undefined, unless such an expression is a constant
expression (5.19), in which case the program is ill-formed.

That implies that the above snippets do not involve undefined behavior.
Instead, they might be ill-formed.
Best

Kai-Uwe Bux
Aug 27 '06 #27
Jerry Coffin <jc*****@taeus.comwrote:
>Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
>No, it does not have to be evaluated at compile time. That is not a
requirement and never has been.
"A constant expression that evaluates to zero can be implicitly
converted to any pointer or pointer to member type." (Stroustrup)

I see no way of implementing this in a safe fashion
unless the expression is evaluated at compile time. The only
alternative would seem to be liberally allowing non-zero
constant integer expressions to be assigned to pointers,
which seems a very bad alternative.

Am I missing something?

Steve
Aug 27 '06 #28
* Steve Pope:
Jerry Coffin <jc*****@taeus.comwrote:
>>Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
>No, it does not have to be evaluated at compile time. That is not a
requirement and never has been.

"A constant expression that evaluates to zero can be implicitly
converted to any pointer or pointer to member type." (Stroustrup)

I see no way of implementing this in a safe fashion
unless the expression is evaluated at compile time. The only
alternative would seem to be liberally allowing non-zero
constant integer expressions to be assigned to pointers,
which seems a very bad alternative.

Am I missing something?
Yes: your left shift expression

pi = 1 << 100;

does /not/ necessarily evaluate to zero.

If an int has 101 or more significant bits, the value will be non-zero.

If it has less than 101 bits, which is probably the case for all current
commercial C++ implementations, then the expression yields Undefined
Behavior, meaning that if it produces a value (which it needs not do
under UB), that value can be anyhing whatsoever.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Aug 27 '06 #29
Alf P. Steinbach <al***@start.nowrote:
Steve Pope:
>"A constant expression that evaluates to zero can be implicitly
converted to any pointer or pointer to member type." (Stroustrup)
>I see no way of implementing this in a safe fashion
unless the expression is evaluated at compile time. The only
alternative would seem to be liberally allowing non-zero
constant integer expressions to be assigned to pointers,
which seems a very bad alternative.
>Am I missing something?
>Yes: your left shift expression

pi = 1 << 100;
>does /not/ necessarily evaluate to zero.
Yes, in my statement above I was speaking about the general
case, not this particular constant expression, but I may not
have made that clear.
Steve
Aug 27 '06 #30
* Steve Pope:
Alf P. Steinbach <al***@start.nowrote:
>Steve Pope:
>>"A constant expression that evaluates to zero can be implicitly
converted to any pointer or pointer to member type." (Stroustrup)
>>I see no way of implementing this in a safe fashion
unless the expression is evaluated at compile time. The only
alternative would seem to be liberally allowing non-zero
constant integer expressions to be assigned to pointers,
which seems a very bad alternative.
>>Am I missing something?
>Yes: your left shift expression

pi = 1 << 100;
>does /not/ necessarily evaluate to zero.

Yes, in my statement above I was speaking about the general
case, not this particular constant expression, but I may not
have made that clear.
While we're at it, I think Kai-Uwe has a point that it's an ill-formed
program instead of UB. Although cases of compile time UB do exist. So
I shouldn't have written UB. :-(

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Aug 27 '06 #31
Alf P. Steinbach <al***@start.nowrote:
While we're at it, I think Kai-Uwe has a point that it's an
ill-formed program instead of UB. Although cases of compile
time UB do exist. So I shouldn't have written UB. :-(
Nods. Kai-Uwe, thanks for providing a clear answer here...

Steve
Aug 27 '06 #32
Jack Klein wrote:
"Noah Roberts" <ro**********@gmail.com>

static_cast<int>((1L << 32) - 1);
Useless cast.
This will work if int is 32 bits.

Only if long has more than 32 bits.
It will fail if LONG_MAX is less than 2^32. This could
happen if long is 33 bits (or more on the DS9000).

Aug 27 '06 #33
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...
Jerry Coffin <jc*****@taeus.comwrote:
Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
No, it does not have to be evaluated at compile time. That is not a
requirement and never has been.

"A constant expression that evaluates to zero can be implicitly
converted to any pointer or pointer to member type." (Stroustrup)
True, but 100% irrelevant. For the umpteenth time: this is NOT a
constant expression with the value zero. In fact, it doesn't have any
defined value at all. It has undefined behavior, nothing less and
nothing more.
I see no way of implementing this in a safe fashion
unless the expression is evaluated at compile time. The only
alternative would seem to be liberally allowing non-zero
constant integer expressions to be assigned to pointers,
which seems a very bad alternative.

Am I missing something?
You're missing the fact that this is NOT an integer constant expression
with the value zero. It's an expression that has undefined behavior.
Since it's not defined (as zero or anything else) the compiler can do
pretty much anything it wants -- it can evaluate it at runtime, or it
can evaluate it at compile time, or it can simply refuse to accept the
code at all. That's the nature of undefined behavior.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 28 '06 #34
In article <ec**********@murdoch.acc.Virginia.EDU>, jk********@gmx.net
says...

[ ... ]
I tend to disagree: the code snippet in question is:

int foo() {
int *pi;
pi = 1 << 100;
}

The assignment pi = 1 << 100 requires the right hand side to be a null
pointer constant, i.e., "an integral constant expression (5.19) rvalue of
integer type that evaluates to zero" [4.10/1]. Since an integral constant
expression is required in the statement, [3.2/2] applies, telling us that
this expression is *not* potentially evaluated. This implies that the
abstract machine is not involved. Instead the compiler is supposed to
magically know the value of the expression.

Also, notice that 1 << 100 by itself is a constant integral expression,
whence [5/5] applies:

If during the evaluation of an expression, the result is not
mathematically defined or not in the range of representable values for its
type, the behavior is undefined, unless such an expression is a constant
expression (5.19), in which case the program is ill-formed.

That implies that the above snippets do not involve undefined behavior.
Instead, they might be ill-formed.
This, at least, strikes me as a reasonable and rational argument, though
I can't say I really agree with it. As I see it, the difference is that
with most operators, the description of that operator simply doesn't
attempt to describe the result when/if there is overflow. By contrast,
in the case of a shift operator, the definition of the operator itself
explicitly does say the result is undefined if the value of the right
operand is greater than the size of the promoted left operand.

IMO, this should be treated much like a program -- if there are
definitions at two different scopes, the definition to use is the one at
the more local scope. As such, I think the statement at 5/5 about
whether or not something is undefined or ill-formed should not be
applied when it is explicitly stated to be undefined behavior in the
definition of the shift opreator itself.

OTOH, I'll grant that I don't know of anything in the standard that
explicitly resolves such a situation, so I can't say it would really be
wrong to resolve it in the way you suggest.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 28 '06 #35
Jerry Coffin <jc*****@taeus.comwrote:
sp*****@speedymail.org says...
>Jerry Coffin <jc*****@taeus.comwrote:
>Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
>No, it does not have to be evaluated at compile time. That is not a
requirement and never has been.
>"A constant expression that evaluates to zero can be implicitly
converted to any pointer or pointer to member type." (Stroustrup)
>True, but 100% irrelevant.
It's completely relevant to my original statement in this thread --
that the code generated does not contain a left-shift instruction
because the constant expression is reduced by the compiler.
You've taken the position that this isn't necessarily true.
I've taken the position that it is necessarily true in the
case of a constant expression being assigned to a pointer.
For the umpteenth time: this is NOT a constant expression
with the value zero. In fact, it doesn't have any defined value
at all.
I'm perfectly aware of this.
>I see no way of implementing this in a safe fashion
unless the expression is evaluated at compile time. The only
alternative would seem to be liberally allowing non-zero
constant integer expressions to be assigned to pointers,
which seems a very bad alternative.
>Am I missing something?
You're missing the fact that this is NOT an integer constant
expression with the value zero.
You've lost me at this point. That I can tell you haven't suggested
a safe, alternate implementation.

Steve
Aug 28 '06 #36
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...

[ ... ]
It's completely relevant to my original statement in this thread --
that the code generated does not contain a left-shift instruction
because the constant expression is reduced by the compiler.
As I've pointed out, while it can be, there's no requirement for that to
be true.
You've taken the position that this isn't necessarily true.
I haven't taken the position -- I've simply pointed out the position
taken by the standard.
I've taken the position that it is necessarily true in the
case of a constant expression being assigned to a pointer.
If you think it's necessarily true, please point to part of the standard
that says or at least implies that it should be. I've already quoted the
parts that say it places no requirement on this code whatsoever.
You're missing the fact that this is NOT an integer constant
expression with the value zero.

You've lost me at this point. That I can tell you haven't suggested
a safe, alternate implementation.
There's no requirement for a safe alternate implementation. For
undefined behavior, the compiler is free to produce absolutely as unsafe
of code as it wants.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 28 '06 #37
Bo Persson wrote:
"Steve Pope" <sp*****@speedymail.orgskrev i meddelandet
And actually, if the constant expression reduces to zero and is
assigned to a pointer, it's probably incorrect for the compiler
not to reduce it; but maybe those more expert than I might have
an opinion on this.

Do you mean that compile time constant expressions should be evaluated
differently than non-constant expressions? Shouldn't we expect the
same result?
No, this is well-known. Adding the requirement would make life truly
hard
for cross-compilers, especially with regard to non-integral constant
expressions.
But even for the special case of ICEs it's not considered worth the
trouble.
To be more technical, the standard doesn't talk about compilers at
all - we could very well have an interpreter, or some other kind of
translator. And *if* a compiler does a compile time evaluation, is it
not supposed to use the hardware instructions itself, internally?
No - as it probably is running on a different CPU. It may be the same
CPU family, in which case we wouldn't call it a cross-compiler, but
even
then the results might differ (Pentium FDIV anyone?). Considering that,
you can't talk about *the* hardware instructions aymore.

Regards,
Michiel Salters

Aug 28 '06 #38

Victor Bazarov wrote:
Mi*************@tomtom.com wrote:
Thomas Tutone wrote:
Because on your system, the number of bits in an int is less than or
equal to 32. And that means that, on your system, (1 << 32) is equal
to 0.
No. Why would it? The most trivial example why it won't is because the
actual CPU has 32 bits and a built-in instruction for << that takes
just 5
bits. On such systems, A<<N == A<<(N%32) because all higher bits
are simply ignored. On such systems 1<<32 == 1. Or the CPU may just
decide to abort the program because it's buggy.

Whatever conclusions you're trying to make from whatever knowledge you
possess about the hardware are nonconsequential; the Standard says that
the behaviour ... is *undefined*.
True, I know. I'm giving a rationale here *why* it's undefined. And
that is because
reasonable hardware might be unable to support it.

Regards,
Michiel Salters

Aug 28 '06 #39
Jerry Coffin <jc*****@taeus.comwrote:
>>sp*****@speedymail.org says...
>Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
If you think it's necessarily true, please point to part of
the standard that says or at least implies that it should be.
Section 4: "An expression e can be implicitly converted to
a type T if and only if the declaration T t = e is well-formed".

Consider

int *p = 2 - 2;
int *q = 2 - 1;

It's required that an implementation accept the first
of these two statements, but not the second. Having the
second merely result in undefined behavior is not a correct
implementation because it performed an implicit conversion
that is disallowed -- violating the "only if" part of the
above spec.

However, one could argue that evaluating the constant expression at
runtime and issuing a runtime error ("dynamic type mismatch", or
some such) would be a correct implementation. I'm not sure
if that's a valid argument, but it's certainly an unattractive
solution.

Steve
Aug 28 '06 #40
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...
Jerry Coffin <jc*****@taeus.comwrote:
>sp*****@speedymail.org says...
Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
If you think it's necessarily true, please point to part of
the standard that says or at least implies that it should be.

Section 4: "An expression e can be implicitly converted to
a type T if and only if the declaration T t = e is well-formed".
That doesn't mention anything about "compile time".

[ ... ]
However, one could argue that evaluating the constant expression at
runtime and issuing a runtime error ("dynamic type mismatch", or
some such) would be a correct implementation.
One certainly could. I believe one would have exceptional difficulty
finding anything to the contrary in the standard.
I'm not sure if that's a valid argument, but it's certainly an
unattractive solution.
I'm pretty sure it is a valid argument. IMO, when C++ is implemented as
a compiler, it's better for as many errors as possible to prevent
compilation, rather than resulting in runtime errors. That, however, is
a personal opinion about quality of implementation -- while I'm fairly
sure some parts of the standard were written to allow and perhaps even
subtly encourage it, I don't believe it's a requirement.

As far as being unattractive: it depends. I can think of some fair
reasons for using a C++ interpreter, and an interpreter more or less
eliminates the whole concept of "compile time"...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 29 '06 #41
Jerry Coffin wrote:
In article <ec**********@blue.rahul.net>, sp*****@speedymail.org says...
>Jerry Coffin <jc*****@taeus.comwrote:
>>sp*****@speedymail.org says...
>Do you agree or disagree that a constant expression being
assigned to a pointer must be evaluated at compile time?
If you think it's necessarily true, please point to part of
the standard that says or at least implies that it should be.

Section 4: "An expression e can be implicitly converted to
a type T if and only if the declaration T t = e is well-formed".

That doesn't mention anything about "compile time".

[ ... ]
>However, one could argue that evaluating the constant expression at
runtime and issuing a runtime error ("dynamic type mismatch", or
some such) would be a correct implementation.

One certainly could. I believe one would have exceptional difficulty
finding anything to the contrary in the standard.
>I'm not sure if that's a valid argument, but it's certainly an
unattractive solution.

I'm pretty sure it is a valid argument. IMO, when C++ is implemented as
a compiler, it's better for as many errors as possible to prevent
compilation, rather than resulting in runtime errors. That, however, is
a personal opinion about quality of implementation -- while I'm fairly
sure some parts of the standard were written to allow and perhaps even
subtly encourage it, I don't believe it's a requirement.
Hm, I am not sure. [1.4/2] says:

Although this International Standard states only requirements on C++
implementations, those requirements are often easier to understand if they
are phrased as requirements on programs, parts of programs, or execution
of programs. Such requirements have the following meaning:

? If a program contains no violations of the rules in this International
Standard, a conforming implementation shall, within its resource limits,
accept and correctly execute3) that program.
? If a program contains a violation of any diagnosable rule, a conforming
implementation shall issue at least one diagnostic message, except that
? If a program contains a violation of a rule for which no diagnostic is
required, this International Standard places no requirement on
implementations with respect to that program.

Now, I would maintain that it is the "implementation" which is required to
issue a diagnostic message of a diagnosable rule and not the program during
its execution. Thus, if the implementation is a compiler (so that it is
observable whether the implementation or the program issues the message),
diagnostics for diagnosable rules have to be issued by the compiler. At
least that is how I read the second item in the list.

In particular: if I compile a program but never run it, a successful compile
without diagnostics should mean that the program satisfies all diagnosable
rules for which diagnostics are not explicitly waived.
As far as being unattractive: it depends. I can think of some fair
reasons for using a C++ interpreter, and an interpreter more or less
eliminates the whole concept of "compile time"...
True, and in that case, you cannot really observe whether the implementation
or the program issues the diagnostics. However, the standard says it should
be the implementation.
Best

Kai-Uwe Bux
Aug 29 '06 #42
In article <ed**********@murdoch.acc.Virginia.EDU>, jk********@gmx.net
says...

[ ... diagnosing at compile time rather than execution time: ]
Hm, I am not sure. [1.4/2] says:
[ ... ]
? If a program contains no violations of the rules in this International
Standard, a conforming implementation shall, within its resource limits,
accept and correctly execute3) that program.
[ ... ]
Now, I would maintain that it is the "implementation" which is required to
issue a diagnostic message of a diagnosable rule and not the program during
its execution.
I've re-quoted part of your quote from the standard above. This makes it
quite clear that it is the implementation that executes the program --
as such, things that are part of the implementation can quite reasonably
happen at execution time.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 29 '06 #43
Jerry Coffin <jc*****@taeus.comwrote:
sp*****@speedymail.org says...
>Section 4: "An expression e can be implicitly converted to
a type T if and only if the declaration T t = e is well-formed".
>That doesn't mention anything about "compile time".
>However, one could argue that evaluating the constant expression at
runtime and issuing a runtime error ("dynamic type mismatch", or
some such) would be a correct implementation.
>One certainly could. I believe one would have exceptional difficulty
finding anything to the contrary in the standard.
>I'm not sure if that's a valid argument, but it's certainly an
unattractive solution.
I'm pretty sure it is a valid argument.
Okay, I now agree with your position -- the constant evaluation
can occur at runtime if a resulting type mismatch causes a
runtime error.

Had you said this in the first place, rather than making
misleading arguments about undefined behavior that completely
missed the point, we would have been in agreement far sooner.

Steve
Aug 29 '06 #44
In article <ed**********@blue.rahul.net>, sp*****@speedymail.org says...

[ ... ]
Had you said this in the first place, rather than making
misleading arguments about undefined behavior that completely
missed the point, we would have been in agreement far sooner.
I certainly didn't intend anything I said to be misleading.

The original piece of code included undefined behavior -- and I'm
reasonably convinced that undefined behavior "trumps" nearly anything
else -- undefined behavior removes the requirement for a diagnostic
(along with all other requirements).

The more recent bit of code you posted did not include undefined
behavior -- and in its absence, I'm reasonably certain a diagnostic is
required.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 29 '06 #45
Jerry Coffin wrote:
In article <ed**********@murdoch.acc.Virginia.EDU>, jk********@gmx.net
says...

[ ... diagnosing at compile time rather than execution time: ]
>Hm, I am not sure. [1.4/2] says:

[ ... ]
> ? If a program contains no violations of the rules in this
International
Standard, a conforming implementation shall, within its resource
limits, accept and correctly execute3) that program.

[ ... ]
>Now, I would maintain that it is the "implementation" which is required
to issue a diagnostic message of a diagnosable rule and not the program
during its execution.

I've re-quoted part of your quote from the standard above. This makes it
quite clear that it is the implementation that executes the program --
as such, things that are part of the implementation can quite reasonably
happen at execution time.
The sentence that you emphasized only deals with programs that contain no
violations of any diagnosable rules and only requires that those programs
be executed. The sentence does not apply at all to programs that violate
any diagnosable rule and neither gives any license nor any requirement for
what an implementation is supposed to do about those programs.

Now, as far as the execution of programs that violate rules is concerned,
you will find relevant language in [1.4/8]:

A conforming implementation may have extensions (including additional
library functions), provided they do not alter the behavior of any
well-formed program. Implementations are required to diagnose programs
that use such extensions that are ill-formed according to this
International Standard. Having done so, however, they can compile and
execute such programs.

Note that the standard demands that the diagnostics are given *before* the
program is executed ("Having done so").

Thus, although

int* p;
p = 1;

is ill-formed an implementation may take the license to compile and execute
a program containing those line (as an extension), but it is required to
flag the error beforehand.
Best

Kai-Uwe Bux
Aug 29 '06 #46
In article <ed**********@murdoch.acc.Virginia.EDU>, jk********@gmx.net
says...

[ ... ]
A conforming implementation may have extensions (including additional
library functions), provided they do not alter the behavior of any
well-formed program. Implementations are required to diagnose programs
that use such extensions that are ill-formed according to this
International Standard. Having done so, however, they can compile and
execute such programs.

Note that the standard demands that the diagnostics are given *before* the
program is executed ("Having done so").
By this reading, it's also required to issue the diagnostic *before*
compiling the program. Given that it's normally the compiler the issues
such diagnostics, I think you're reading more into it than is really
there...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 29 '06 #47
Jerry Coffin wrote:
In article <ed**********@murdoch.acc.Virginia.EDU>, jk********@gmx.net
says...

[ ... ]
> A conforming implementation may have extensions (including additional
library functions), provided they do not alter the behavior of any
well-formed program. Implementations are required to diagnose programs
that use such extensions that are ill-formed according to this
International Standard. Having done so, however, they can compile and
execute such programs.

Note that the standard demands that the diagnostics are given *before*
the program is executed ("Having done so").

By this reading, it's also required to issue the diagnostic *before*
compiling the program. Given that it's normally the compiler the issues
such diagnostics, I think you're reading more into it than is really
there...
I in this context, I would read compiling as "producing the executable". I
agree that the language could be more decisive, however I think, the intent
or at least the desire for compile-time diagnostics is clear.

Also, consider the case where a program is not run (e.g., intermediate
stages in debugging where you just compile to check whether you introduced
typos). Where do you find the language in the standard that waives the
required diagnostics, i.e., where do you find that diagnostics is only
required *if* the program is actually run?

Finally, what about programs like this:

#include <iostream>

int main ( void ) {
int i = 0;
int * p = 0;
if ( std::cin >i ) {
p = 1;
}
}

This program is ill-formed, however, a naive run-time check will only flag
that for certain inputs. I think the standard does not give license to only
flag those ill-formed lines that are executed for a particular input.
Best

Kai-Uwe Bux
Aug 30 '06 #48
Kai-Uwe Bux <jk********@gmx.netwrote:
>Finally, what about programs like this:

#include <iostream>

int main ( void ) {
int i = 0;
int * p = 0;
if ( std::cin >i ) {
p = 1;
}
}
This program is ill-formed, however, a naive run-time check
will only flag that for certain inputs. I think the standard
does not give license to only flag those ill-formed lines that
are executed for a particular input.
A good way to resolve this, but one I don't see in the standard,
is not to allow partial execution of any ill-formed program.
If that is not in the standard, perhaps it is a deliberate omission
to allow interpreters.

Another possibility is that any ability to partially execute an
ill-formed program constitutes a "language extension" and the rules
you quoted previously apply.

Steve
Aug 30 '06 #49
In article <ed**********@murdoch.acc.Virginia.EDU>, jk********@gmx.net
says...

[ ... ]
I in this context, I would read compiling as "producing the executable". I
agree that the language could be more decisive, however I think, the intent
or at least the desire for compile-time diagnostics is clear.
In $1.9/1, they say:

This International Standard places no requirement on the
structure of conforming implementations. In particular,
they need not copy or emulate the structure of the abstract
machine. Rather, conforming implementations are required to
emulate (only) the observable behavior of the abstract
machine as explained below.

My guess is that it's a relatively simple situation: most of the authors
are sufficiently accustomed to a compiler type of implementation that
they more or less take it for granted in their writing, even though they
clearly don't intend that it be a requirement.

[ ... ]
This program is ill-formed, however, a naive run-time check will only flag
that for certain inputs. I think the standard does not give license to only
flag those ill-formed lines that are executed for a particular input.
I think from a viewpoint of conformance, this is almost entirely a QOI
issue. The requirement is ($1.4/2):

If a program contains a violation of any diagnosable rule,
a conforming implementation shall issue at least one
diagnostic message, except that If a program contains a
violation of a rule for which no diagnostic is required,
this International Standard places no requirement on
implementations with respect to that program.

Strictly from a viewpoint of conforming, that's trivial to meet: simply
issue a diagnostic before commencing interpretation of anything. If you
wanted to conform without modifying your code, change the documentation
to say your copyright notice was a "diagnostic" and you'd be done.

I'll openly admit that's probably not what anybody wanted or intended,
but I can't think of any part of the standad it'd violate either...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 31 '06 #50

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Kevin | last post: by
2 posts views Thread by Saber S | last post: by
11 posts views Thread by Kenneth Lantrip | last post: by
19 posts views Thread by aurgathor | last post: by
1 post views Thread by jonathanmcdougall | last post: by
4 posts views Thread by sandhya | last post: by
15 posts views Thread by Christopher Layne | last post: by
4 posts views Thread by G Iveco | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.