On Thu, 12 Oct 2006 05:30:24 +0000 (UTC),
sp*****@speedymail.org
(Steve Pope) wrote in comp.lang.c++:
techie <te****@nospam.bizwrote:
I have defined a number of unsigned integer types as follows:
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedfe long long uint64;
Is it necessary to explicitly cast from one type of unsigned integer type to
another even though they do so implicitly?
e.g. bytes0_1 |= (static_cast<uint16>(VersionNo)) << 12;
bytes0_1 is of type uint16. Here I thought it is safer to cast VersionNo
(type uint8) to uint16 before I do a left shift. I was just a bit worried
about shifting the digits off the end of an 8 bit number. Likewise in the
statement below I cast the result of the left shift and bit wise addition to
uint64.
byte6 = static_cast<uint8>((MAC_Adddress >40) & 0xFF);
MAC_Adddress is of type uint64.
When I run QA C++ (source code analyzer) on my code it issues a few warnings
for the first statement:
Bitwise operator is being applied to a signed type.
In your first expression the right-hand side has two operands.
The wider of these operands is the constant 12, which is
of type int, and is therefore (probably) 32 bits wide (on
many systems). The other operand, which is the expression
(static_cast<uint16>(VersionNo)), is promoted to being 32 bits
wide to match the wider operand.
No, that is not correct for the bitwise shift operators. The left and
right operands do not need to be converted to the same type.
The integer promotions would apply to the argument on the right if and
only if it were a narrower type than int. Since the plain integer
literal "12" already has type int, no change is necessary. This has
nothing at all to do with the number of bits in an int.
The cast forces a conversion "VersionNo" from unsigned char to
unsigned short. Then it is automatically converted to either int or
unsigned int. Since the OP has told us by his typedef that int has 32
bits on his platform, and a signed 32-bit int can hold all the
possible values of an unsigned 16-bit short, it is converted to signed
int, not unsigned int.
See paragraph 1 of 4.5 of the C++ standard.
Then the 12 is promoted to
unsigned (if either operand is unsigned, the other becomes
unsigned).
The type of the left hand operand in bitwise shift operator
expressions has nothing at all to do with the type or any conversions
performed on the right hand operator. "12" starts out as an int and
stays an int.
There is no need to convert the two operands of the bitwise shift
operators to the same type, as they are never directly combined. The
bitwise shift binary operators are different from the arithmetic and
bitwise AND, OR, and XCR operations in this respect.
See 5.8 of the C++ standard, and note the omission of the phrase "the
usual arithmetic conversions are performed".
The result of the shift operation is an unsigned
int (32 bits), which is then automatically cast down to the width
of the left hand side, which is 16 bits unsigned.
There are two errors in the paragraph above. First is the fact that
since the left hand operand of the shift operator is a signed int, the
result also has the type signed int.
It is not "automatically cast", there is no such thing. C++ has
conversions, some of which are automatic and some of which require a
cast. A cast is only performed by one of the cast operators, and
tells the compiler to perform an explicit conversion, one which might
or might not have happened automatically in the absence of the cast.
The OP did not specify the type of the destination "bytes0_1", but if
it is not signed int, the result of the shift operator is
automatically converted to that type.
I do not particularly understand why the compiler gave you this
particular warning, but it seems to derive from the implicit
promotion of the signed constant 12 to an unsigned value.
There is no promotion or conversion at all of the integer literal "12"
to an unsigned value. It has type int, and it remains type int in the
expression.
The warning is because the unsigned 16-bit short promoted to a signed
32-bit int.
C++ inherits its integer promotion rules from ISO C, and those rules
are "value preserving" rather than "sign preserving".
When an unsigned integer type of lesser rank than int is being
promoted to int, it is promoted to signed int if the entire range of
values of the lesser unsigned type is within the range of positive
values in a signed int.
On an implementation with 16-bit shorts and 16-bit ints, an unsigned
short would promote to unsigned int. On an implementation with 16-bit
shorts and 32-bit ints, an unsigned short promotes to signed int.
--
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