I have run into an issue when performing arithmetic left-shifts in C with Keil when the shift operand is a constant. Specifically, if the operand is a constant and specifies a shift value larger than the size of the variable, e.g. >32 when the destination variable is an unsigned long, then the value to be shifted is wrapped around! For example,
unsigned long ulvar; ulvar = 1UL << 33; Result: ulvar == 2.
This is unexpected behavior. The assumption would have been that ulvar would contain zero (0). Has anybody ever run into this issue or know if this is a feature?
Thanks in advance.
Here is the version of the compiler that I'm using: µVision3 V3.62c Copyright (c) Keil Elektronik GmbH / Keil Software, Inc. 1995 - 2008
Tool Version Numbers: Toolchain: PK51 Prof. Developers Kit: 6 user Version: 8.16 Toolchain Path: C:\Keil\C51\BIN\ C Compiler: C51.Exe V8.16 Assembler: AX51.Exe V3.06a Linker/Locator: LX51.Exe V4.34a Librarian: LIBX51.Exe V4.24 Hex Converter: OHX51.Exe V1.36b CPU DLL: S8051.DLL V3.63 Dialog DLL: DCore51.DLL V2.63b Target DLL: C:\Program Files\Evatronix\EDIk51-3\edi3r8051xc.dll Dialog DLL: TCore51.DLL V2.62
"This is unexpected behavior."
Per the language standard, using a shift count greater than the operand's width is "undefined behavior", so all bets are off. You cannot reasonably expect or assume any kind of result or particular behavior.
And what issue do you think you have?
The C language standard says: "If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behaviour is undefined."
2^33 - 1 = 8589934591 > 2^32 - 1 = 4294967295
All, THANKS for the feedback. Obviously I misunderstood or made a wrong assumption about the C standard behavior of such an operation. I appreciate the clarifications.
this is wrong.
this is right.
2^33 - 1 = 34 and 2^32 - 1 = 33