GetByte(int x, int n)

E

Eric Sosman

Dan said:
In said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Not "the high-order bits of the resulting value," but
"the resulting value, period."

[...]
Wrong. You have no licence to ignore the first statement of the
paragraph, which is limiting the options of the implementor.

It is a wilful (probably) misreading of the Standard
to maintain that the first sentence invalidates the other
two. Consider the similar construction in 7.12.7.5:

The sqrt functions compute the nonnegative
square root of x. A domain error occurs if
the argument is less than zero.

If the first sentence is taken to be inviolable, as you
suggest in the case of right-shift, then sqrt() must compute
a non-negative square root for *every* argument value, even
negative values. This is, of course, nonsense -- so it
follows that the first sentence *can* be ignored under the
circumstances described in the rest of the paragraph.

"The value is implementation-defined" means what it
says: The implementation has complete freedom to produce
any value it chooses, so long as it documents the choice.
See also 3.17.1 and 3.17.3.
 
C

CBFalconer

Dan said:
This is at odds with the actual definition of the right shift operator:

5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E1 has an unsigned type or if E1 has a signed type and a
nonnegative value, the value of the result is the integral
part of the quotient of E1 / 2**E2. If E1 has a signed type and

---------------------------
a negative value, the resulting value is implementation-defined.

---------------------------------------------------------------
The only thing the underlined text leaves up to the implementor to
define is the values of the bits filling the vacated bit positions.
They can be all ones or all zeroes (the only cases one will see in real
world implementations) or some arbitrary bit pattern defined by the
implementor. The bits coming from right-shifting E1 have all well
defined values.

And the other - underlined portion justifies using my otherwise not
too useful definition, which defines the _value_ of a negative
value of a signed type right-shifted some number of positions.
Your underlined sentence doesn't describe the value of that
entity. The real point is "don't do that".
 
D

Dan Pop

In said:
"The value is implementation-defined" means what it
says: The implementation has complete freedom to produce
any value it chooses, so long as it documents the choice.
See also 3.17.1 and 3.17.3.

Nope. Implementation-defined is a special case of unspecified:

1 implementation-defined behavior
unspecified behavior where each implementation documents how
the choice is made

Also note the enlightening non-normative example:

2 EXAMPLE An example of implementation-defined behavior is the
propagation of the high-order bit when a signed integer is
shifted right.

Then,

1 unspecified behavior
behavior where this International Standard provides two or more
^^^^^^^^^^^
possibilities and imposes no further requirements on which is
^^^^^^^^^^^^^
chosen in any instance

That's precisely what the definition of right shifting negative values
does: it provides a restrictive set of possible results and lets the
implementor describe how the choice is made.

Dan
 
E

Eric Sosman

Dan said:
Nope. Implementation-defined is a special case of unspecified:

1 implementation-defined behavior
unspecified behavior where each implementation documents how
the choice is made

That's the definition of implementation-defined
*behavior*, not of an implementation-defined *value*.
The right-shift paragraph says that the *value*, not
the behavior, is implementation-defined -- and once
again, I refer you to the definition of implementation-
defined *value* in 3.17.1:

unspecified value where each implementation
documents how the choice is made

and of unspecified *value* in 3.17.3:

valid value of the relevant type where this
International Standard imposes no requirements
on which value is chosen in any instance

Note the absence of any text similar to that which you
highlighted.
 
T

Tim Rentsch

Eric Sosman said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Not "the high-order bits of the resulting value," but
"the resulting value, period."


Well-defined, yes -- but by the implementation, not by
the Standard.

Before drawing any conclusions, I'd like to suggest a couple of
thought experiments:

Q1. What is the value of the expression '(-3) >> 1'?

Q2. Assuming CHAR_BIT == 8 and sizeof(int) == 4, what is
the value of the expression '((-3) >> 1) & 0x7fffffff'?

Q3. What does the standard say about the values of either
of those expressions?


Both sides have made some good arguments. And there is a sense in
which both points of view could be right - the standard could say what
happens to the bits, but the value still be "implementation-defined".

Ultimately though I think the idea that the bit values are
well-defined even when the left operand is negative falls a little
short. The reason for this is simple: the standard explicitly allows
a signed-magnitude representation scheme for negative integers; if
you think about how right shift would naturally be done for such
numbers, the sign bit wouldn't move, and zeros would be shifted into
the high order (value) bit positions. Clearly the intention would be
that the standard should allow such behavior; and, the resulting bit
values in that case differ from the bit values most of us are used to
for the right shift operation (at least, one of the bit values would
differ).

So, even though a value being "implementation-defined" might not mean
"any value whatsoever", it seems true that different implementations
could yield different bit values after right-shifting and masking.
 
M

Mark Piffer

Umh, are you referring to the given macro or the function/macro I was
describing?
The macro 20 lines above which I quoted.
The macro at hand will give you not more problems if
sizeof long > sizeof int.
What sizeof int - 1 has to do with it, I am not sure at all.

Let us, for a moment, assume that we do not use the macro for negative
x and have inserted the parentheses. UCHAR_MAX << u*CHAR_BIT will not
have overlapping non-zero bits with x if u >= sizeof x. As
UCHAR_MAX << u*CHAR_BIT is considered unsigned and a multiple of
Why is it considered unsigned? I can't find any indication for it
being unsigned.
exp2(u*CHAR_BIT), it is effectively 0 if we shift "out of" the largest
unsigned type. Now we consider the case u == sizeof x - 1.
What can go wrong? Assume CHAR_BIT==8, sizeof x==2, x=(T*2<<12) +
(U*2<<8) + (V*2<<4) + W, written symbolically as 0xTUVW:
0xff << 1*8 --> 0xff00
0xTUVW & 0xff00 --> 0xTU00
0xTU00 >> 1*8 -->0x$$TU. We assumed nonnegative x -->0xTU
If x was negative, we also could have non-zero nibbles instead
of the $ signs. However, this is only unspecified, not undefined.

Maybe you want to elaborate where you think the UB creeps in.

[guess mode]
Lets assume an architecture where sizeof long == 4 and sizeof int ==
2. If you want to extract byte #2 (the byte starting at
2^(2*CHAR_BIT)) of the long argument, your expression will try to
shift the signed integer constant UCHAR_MAX left 2*CHAR_BIT, which is
equal to the width of int, which is UB following 6.5.7/3.
OTOH, if you have sizeof long == sizeof int and both > 1 and want to
extract the highest byte (i.e. sizeof int - 1), you invoke UB because
you shift a positive signed integer so many places left that it can't
be represented in an int, which will cause UB following 6.5.7/4 (last
sentence).
[/guess mode]

Where do I err?

Mark
 
D

Dan Pop

In said:
That's the definition of implementation-defined
*behavior*, not of an implementation-defined *value*.
The right-shift paragraph says that the *value*, not
the behavior, is implementation-defined -- and once
again, I refer you to the definition of implementation-
defined *value* in 3.17.1:

unspecified value where each implementation
documents how the choice is made

and of unspecified *value* in 3.17.3:

valid value of the relevant type where this
International Standard imposes no requirements
on which value is chosen in any instance

Note the absence of any text similar to that which you
highlighted.

You have just discovered an inconsistency in the C standard. Note that
the standard's own example of implementation-defined behaviour actually
refers to an implementation-defined value. You won't find the exact
wording of the example anywhere else in the standard.

Dan
 
M

Mabden

Dan Pop said:
You have just discovered an inconsistency in the C standard.

*>GASP!<*

My world view is very fragile since I heard that the K&R has an errata
web page. Then there was the whole "all zeroes" is not null fiasco. I
read a post by Dan Pop that WASN'T mean! My head is spinning, and not in
a good (tequila and rum drinks) way!

Oy!
 
P

pete

Dan Pop wrote:
The apparent objection that the >> operator has implementation-defined
behaviour if its left operand is signed and negative is moot, because
the bits not well defined by the standard are masked away from the
final result.

If an intermediate result is undefined, then it's all undefined.

The result of a left shift of an int value,
may result in a negative zero.
I believe that can be a trap.
 
E

Eric Sosman

pete said:
If an intermediate result is undefined, then it's all undefined.

First, "implementation-defined" is not "undefined."

Second, although the result is implementation-defined
for the case `(negative_int >> n) & UCHAR_MAX' under
discussion, an implementation-defined operand need not
always produce an implementation-defined result. Here
are a few examples of perfectly predictable results from
expressions involving implementation-defined values:

INT_MAX > INT_MIN == 1
(-1 >> 3) * 0 == 0
(-5 / 3) * 3 + (-5 % 3) == 3

(The last example involves implementation-defined values
in C89, but not in C99.)
The result of a left shift of an int value,
may result in a negative zero.
I believe that can be a trap.

Yes, but we were discussing right shifts. Oddly
enough, (-1 << 3) need not produce any value at all;
the behavior is altogether undefined. That's "odd"
in contrast to (-1 >> 3), which does *not* produce
undefined behavior, and whose implemenation-defined
value cannot be a trap value.
 
P

pete

Eric said:
First, "implementation-defined" is not "undefined."

Second, although the result is implementation-defined
for the case `(negative_int >> n) & UCHAR_MAX' under
discussion, an implementation-defined operand need not
always produce an implementation-defined result. Here
are a few examples of perfectly predictable results from
expressions involving implementation-defined values:

INT_MAX > INT_MIN == 1
(-1 >> 3) * 0 == 0
(-5 / 3) * 3 + (-5 % 3) == 3

(The last example involves implementation-defined values
in C89, but not in C99.)


Yes, but we were discussing right shifts.

Sorry, I get left and right mixed up too much on this newsgroup.
A right shift can result in negative zero.

(1000...0001 >> 1) can be (1000...0000), -0 in signed magnitude
(1111...1110 >> 1) can be (1111...1111), -0 in one's complement
 
D

Dan Pop

In said:
A right shift can result in negative zero.

(1000...0001 >> 1) can be (1000...0000), -0 in signed magnitude
(1111...1110 >> 1) can be (1111...1111), -0 in one's complement

But, since an implementation-defined value *must* be a valid value,
such implementations must treat -0 as an alternate representation of 0.
If they treat -0 as a trap representation, then they must make sure
that no right shift can generate the corresponding bit pattern.


3.17.1
1 implementation-defined value
unspecified value where each implementation documents how the
choice is made

3.17.3
1 unspecified value
valid value of the relevant type where this International Standard
^^^^^^^^^^^
imposes no requirements on which value is chosen in any instance

Dan
 
M

Mark Piffer

Umh, are you referring to the given macro or the function/macro I was
describing?
The macro 20 lines above which I quoted.
The macro at hand will give you not more problems if
sizeof long > sizeof int.
What sizeof int - 1 has to do with it, I am not sure at all.

Let us, for a moment, assume that we do not use the macro for negative
x and have inserted the parentheses. UCHAR_MAX << u*CHAR_BIT will not
have overlapping non-zero bits with x if u >= sizeof x. As
UCHAR_MAX << u*CHAR_BIT is considered unsigned and a multiple of
Why is it considered unsigned? I can't find any indication for it
being unsigned.
exp2(u*CHAR_BIT), it is effectively 0 if we shift "out of" the largest
unsigned type. Now we consider the case u == sizeof x - 1.
What can go wrong? Assume CHAR_BIT==8, sizeof x==2, x=(T*2<<12) +
(U*2<<8) + (V*2<<4) + W, written symbolically as 0xTUVW:
0xff << 1*8 --> 0xff00
0xTUVW & 0xff00 --> 0xTU00
0xTU00 >> 1*8 -->0x$$TU. We assumed nonnegative x -->0xTU
If x was negative, we also could have non-zero nibbles instead
of the $ signs. However, this is only unspecified, not undefined.

Maybe you want to elaborate where you think the UB creeps in.

[guess mode]
Lets assume an architecture where sizeof long == 4 and sizeof int ==
2. If you want to extract byte #2 (the byte starting at
2^(2*CHAR_BIT)) of the long argument,
[Edit: I assume an unsigned long argument given as macro parameter
'x']
your expression will try to
shift the signed integer constant UCHAR_MAX left 2*CHAR_BIT, which is
equal to the width of int, which is UB following 6.5.7/3.
OTOH, if you have sizeof long == sizeof int and both > 1 and want to
extract the highest byte (i.e. sizeof int - 1), you invoke UB because
you shift a positive signed integer so many places left that it can't
be represented in an int, which will cause UB following 6.5.7/4 (last
sentence).
[/guess mode]

Where do I err?

Mark

Sorry to bump this post again, but I didn't get a definitive answer
and I am really interested if my conclusions about the macro
#define GetByte(x, u)\
((x & UCHAR_MAX << u * CHAR_BIT) >> u * CHAR_BIT)
are wrong.

Mark
 
T

Tim Rentsch

(e-mail address removed) (Mark Piffer) wrote in message news:<[email protected]>...

[SNIP, SNIP, SNIP!]
[guess mode]
Lets assume an architecture where sizeof long == 4 and sizeof int ==
2. If you want to extract byte #2 (the byte starting at
2^(2*CHAR_BIT)) of the long argument,
[Edit: I assume an unsigned long argument given as macro parameter
'x']
your expression will try to
shift the signed integer constant UCHAR_MAX left 2*CHAR_BIT, which is
equal to the width of int, which is UB following 6.5.7/3.
OTOH, if you have sizeof long == sizeof int and both > 1 and want to
extract the highest byte (i.e. sizeof int - 1), you invoke UB because
you shift a positive signed integer so many places left that it can't
be represented in an int, which will cause UB following 6.5.7/4 (last
sentence).
[/guess mode]

Where do I err?

Sorry to bump this post again, but I didn't get a definitive answer
and I am really interested if my conclusions about the macro
#define GetByte(x, u)\
((x & UCHAR_MAX << u * CHAR_BIT) >> u * CHAR_BIT)
are wrong.

I believe the answer is, it depends on the definition of UCHAR_MAX.
If UCHAR_MAX is defined

#define UCHAR_MAX (255)

or

#define UCHAR_MAX ((int) 255)

or

#define UCHAR_MAX ((unsigned char) 255)

then the conclusions above are correct (in the last case because of
the ANSI "value preserving rule" for promotions, and assuming that
sizeof(int) > sizeof(char) is true). If UCHAR_MAX is defined

#define UCHAR_MAX (255U)

then the conclusion about the case when sizeof(long) > sizeof(int) is
right but the other conclusion is wrong. If UCHAR_MAX is defined

#define UCHAR_MAX (255UL)

then both conclusions are wrong.

Reading 5.2.4.2.1 p1, the type of UCHAR_MAX is the same as an unsigned
char "converted according to the integer promotion rules", which is
like the first two cases above.

Hence, I believe your conclusions are correct.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top