Is it a defined operation when I do something like this:
char a = 15;
a = a<<9;
Only on systems where char has at least 10 bits.
The relevant Standard cite is 3.3.7 Bitwise shift operators:
"If the value of the right operand is negative or is greater than or equal
to the width in bits of the promoted left operand, the behavior is
undefined."
--
Richard Heathfield <http://www.cpax.org.uk >
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Is it a defined operation when I do something like this:
char a = 15;
a = a<<9;
>
Only on systems where char has at least 10 bits.
>
The relevant Standard cite is 3.3.7 Bitwise shift operators:
>
"If the value of the right operand is negative or is greater than or equal
to the width in bits of the promoted left operand, the behavior is
undefined."
Is there any system out there which will not zero out all the bits?
Is it a defined operation when I do something like
this:
char a = 15;
a = a<<9;
>
Only on systems where char has at least 10 bits.
>
The relevant Standard cite is 3.3.7 Bitwise shift
operators:
>
"If the value of the right operand is negative or is
greater than or equal to the width in bits of the
promoted left operand, the behavior is undefined."
^^^^^^^^
That is almost incidental. The promoted type must have
a width of at least 16.
The problem is that plain char may be signed or
otherwise promote to a narrow int.
n1256: 6.5.7p4
The result of E1 << E2 is E1 left-shifted E2 bit
positions; vacated bits are filled with zeros. ...
If E1 has a signed type and nonnegative value,
and E1x2^E2 is representable in the result type,
then that is the resulting value; otherwise, the
behavior is undefined.
If CHAR_MAX == INT_MAX, then even a shift of 1
could invoke undefined behaviour.
There is also a problem with the assignment if the
shifted value _is_ representable as an int, but
outside the range of plain char.
Neither C90 nor C99 guarantee truncation for narrowing
of signed types. Under C99, an implementation defined
signal may even be raised.
As disasterous as this all sounds, the solution
is very simple. Where possible, stick to unsigned
types for bitwise operations. It is rarely impractical
to do this.
Is it a defined operation when I do something like
this:
char a = 15;
a = a<<9;
>
Is there any system out there which will not zero out
all the bits?
Why don't you state what you're trying to do, rather than
asking if code which you _think_ is the solution to an
(undisclosed problem) is valid?
You should be shifting unsigned types where possible.
It's unusual to shift wider than given type, but not
that unusual to shift _as wide_ as the given type.
If w is the width of an unsigned type, it's easy to
shift by 0..w bits, where a shift of w zeros out the
field...
/* shift by n bits: 0 <= n <= width of u */
if (w) u = u << (n - 1) << 1;
Note that 'width' means the number of (sign plus)
value bits, not necessarily the full size of the
type in bits.
>>Is it a defined operation when I do something like this:
>>char a = 15;
>>a = a<<9;
>Only on systems where char has at least 10 bits.
The value of CHAR_BIT doesn't matter, not directly. The
expression is evaluated this way:
- First, the starting value of `a' is converted from `char'
to `int' (on most systems) or `unsigned int' (on some).
The statement is now equivalent to one of `a = 15 << 9;'
or `a = 15u << 9;'.
- Next, the shift operator is applied. The numerical result
is within the range of both `int' and `unsigned int', so
now we have either `a = 7680;' or `a = 7680u;'.
- Now comes the dodgy part: The result of the shift is
converted from `int' or `unsigned int' to `char'. If
If `char' is unsigned, all is well: the conversion
yields `7680 % (CHAR_MAX+1)', mathematically speaking.
If `char' is signed and if CHAR_MAX >= 7680 (implying
CHAR_BIT >= 14), all is well again and the conversion
yields `(char)7680'. It's the remaining case that makes
trouble: if `char' is signed and CHAR_MAX < 7680, the
conversion takes us into poorly-charted waters, either
yielding an implementation-defined result or raising an
implementation-defined signal.
- Finally (if we get this far), the converted value is
stored in `a'.
So, yes: The value of CHAR_BIT affects the outcome because
it affects the value of CHAR_MAX used in the conversion, but it
does not affect the operation of or validity of the shift. To
illustrate, changing the second line to `int i = a << 9;' yields
a fragment whose behavior is the same on all implementations .
>
...The value of CHAR_BIT affects the outcome because
it affects the value of CHAR_MAX used in the conversion,
but it does not affect the operation of or validity of
the shift.
>
... changing the second line to `int i = a << 9;'
yields a fragment whose behavior is the same on all
implementations .
If CHAR_MAX <= INT_MAX and a (INT_MAX >9), then the
behaviour of a << 9 is undefined.
In article
<f8aa0754-b029-4b88-909d-1829e884a737@k7 g2000hsd.google groups.com>, Peter
Nilsson <airia@acay.com .auwrote:
[...]
If w is the width of an unsigned type, it's easy to
shift by 0..w bits, where a shift of w zeros out the
field...
>
/* shift by n bits: 0 <= n <= width of u */
if (w) u = u << (n - 1) << 1;
>
Note that 'width' means the number of (sign plus)
value bits, not necessarily the full size of the
type in bits.
Even though the comment claims that n can be 0, the code causes UB for n=0
due to n-1. Even if the n-1 issue is solved, you still have the
unconditional shift left by 1 to deal with. How about something like
On Wed, 1 Oct 2008 23:43:12 -0700 (PDT), Peter Nilsson
<airia@acay.com .auwrote in comp.lang.c:
Richard Heathfield <r...@see.sig.i nvalidwrote:
British0zzy said:
Is it a defined operation when I do something like
this:
char a = 15;
a = a<<9;
Only on systems where char has at least 10 bits.
The relevant Standard cite is 3.3.7 Bitwise shift
operators:
"If the value of the right operand is negative or is
greater than or equal to the width in bits of the
promoted left operand, the behavior is undefined."
^^^^^^^^
>
That is almost incidental. The promoted type must have
a width of at least 16.
>
The problem is that plain char may be signed or
otherwise promote to a narrow int.
What exactly do you mean by "promote to a narrower int"? How can int
be narrower than int?
Did you mean "promote to a narrower integer type than int"? If so,
chapter and verse, please.
>>>British0zz y said:
>>>>char a = 15;
>>>>a = a<<9;
>...The value of CHAR_BIT affects the outcome because
>it affects the value of CHAR_MAX used in the conversion,
>but it does not affect the operation of or validity of
>the shift.
>>
>... changing the second line to `int i = a << 9;'
>yields a fragment whose behavior is the same on all
>implementation s.
>
If CHAR_MAX <= INT_MAX and a (INT_MAX >9), then the
behaviour of a << 9 is undefined.
Yes. But since INT_MAX is at least 32767, then
INT_MAX>>9 is at least 63, a number greater than the
value of `a'. The second half of your premise never
holds, so the conclusion does not apply.
Peter Nilsson <ai...@acay.com .auwrote in comp.lang.c:
Richard Heathfield <r...@see.sig.i nvalidwrote:
British0zzy said:
Is it a defined operation when I do something like
this:
char a = 15;
a = a<<9;
>
Only on systems where char has at least 10 bits.
>
The relevant Standard cite is 3.3.7 Bitwise shift
operators:
>
"If the value of the right operand is negative or is
greater than or equal to the width in bits of the
promoted left operand, the behavior is undefined."
^^^^^^^^
That is almost incidental. The promoted type must have
a width of at least 16.
The problem is that plain char may be signed or
otherwise promote to a narrow int.
>
What exactly do you mean by "promote to a narrower int"?
Since I didn't write that, I can't answer you. :-)
What I mean by 'narrow int' is that if plain char promotes
to int, then int must be at least 9 bits wider than plain
char for a left shift of 9 bits to be guaranteed to work
work for arbitrary char values. [Obviously, there is still
the problem of assigning the shifted value back to char.]
Comment