undefined behavior when left operand is negative - c

few days back I gave Microsoft GD online exam for internship there. I have always studied that the left shift of negative number is an undefined behavior but that paper had almost 7 questions out of 30 related to shift operators and approx 5 questions were ther which involved shifting negative numbers to left and they had no option saying "undefined behavior". I was shocked to see that . So, my question is that has this C standard changed ? Is this defined now ?
sample question :
printf("%d",-1<<10);
I marked its answer as -1024 by the logic 2^10*-1
I even ran this on gcc and it gave me o/p as -1024 nly (when I returned home.)

The rules haven't changed. It's still technically undefined.
Quoting from the C standard (Section 6.5.7, paragraph 4, of n1548):
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.
It clearly says if E1 is not unsigned or signed with nonnegative value, the behavior is undefined.

In the shift operrators >> or <<:
operands should be of integral type or subject to integral promotion.
If right operand is negative or greater than the bits in left operand then Undefined behaviour
if left operand is negative with >> then it's implementation defiend and with << undefined behaviour
Quoting from K&R Appendix-A
The shift operators << and >> group left-to-right. For both operators,
each operand must be integral, and is subject to integral the promotions.
The type of the result is that of the promoted left operand.
The result is undefined if the right operand is negative,
or greater than or equal to the number of bits in the left expression's type.
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
The value of E1<<E2 is E1 (interpreted as a bit pattern) left-shifted E2 bits;
in the absence of overflow, this is equivalent to multiplication by 2. The value
of E1>>E2 is E1 right-shifted E2 bit positions. The right shift is equivalent to division
by 2. if E1 is unsigned or it has a non-negative value; otherwise the result is
implementation-defined.

Perhaps you were thinking that the right operand is negative?
http://msdn.microsoft.com/en-us/library/336xbhcz(v=vs.80).aspx

Related

Question about using bitshift operators on int

I am a beginner so dont get mad at my simple question but suppose I have an int variable
lets say a, and I do a<<3 will that be equal to a*2^3 = a*8 as I read that bitshift operators multiply the variable with 2^x.
Am I correct or I am misreading this situation??
Thanks!
Yes, with some exceptions.
Consider 123410 × 103 = 123400010. We added zeroes to the right of the decimal representation of the number by multiplying it by a power of ten.
Similarly, we can add zeroes to the right of the binary representation of the number by multiplying it by a power of two. For example, 10112 × 23 = 10110002.
The exceptions fall into two categories.
Exceptions due to overflow
If the left operand has an unsigned type, and the result is too large for that type, the most significant bits will be dropped.
For example, in an environment with a 32-bit unsigned int type, 8000000116 × 21 = 1000000216, but 0x80000001u << 1 produces the chopped result 0x0000002u.
If the left operand has an signed type, and the result is too large for that type, the behaviour is undefined.
For example, in an environment with a 32-bit int type, the behaviour of 1 << 31 is undefined.
Exceptions due to weird operands
If the value of the right operand is negative, the behaviour is undefined.
For example, the behaviour of 1 << -1 is undefined.
If the value of the left operand is negative, the behaviour is undefined.
For example, the behaviour of -1 << 1 is undefined.
If the value of the right operand is greater than or equal to the width of the promoted left operand, the behaviour is undefined.
For example, in an environment with a 32-bit unsigned int type, the behaviour of 1u << 32 is undefined.
C17, on the semantics of <<:
The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
Left shift simply means to shift the set binary values to some places to the left. for example, 3 has a binary value of 11 so doing 3<<3 means we left shift these set bits (1) to 3 places to the left. so 11 becomes 11000 which is equal to 24.
You are correct! By bitshifting to the left you multiply your integer value with 2.
Visualising it, you do the following:
Let's say a is an 8-bit integer and is equal to 1.
That means that the binary code will look like: 00000001
Now if we bit shift 3 times to the left, that binary code becomes 00001000, which is 8.

Shift by type width does not return zero [duplicate]

This question already has answers here:
Weird behavior of right shift operator (1 >> 32)
(7 answers)
Closed 6 years ago.
For a simple obfuscation assignment, I would need to shift an unsigned int until it becomes zero.
unsigned int a = 12;
a <<= sizeof(a) * 8;
printf("%u", a);
I compile it using gcc test.c -o bin, GCC warnings:
warning: left shift count >= width of type [-Wshift-count-overflow]
When I execute it, it returns 12. But it should be 0 undoubtedly. Has GCC ignored compiling that line of code? or I'm missing something?
This is undefined behavior.
In any case, if the value of the right operand [of << or >>] is negative or is greater or equal to the number of bits in the promoted left operand, the behavior is undefined.
(quote from http://en.cppreference.com/w/cpp/language/operator_arithmetic)
Also, the article says that:
Unsigned overflow and underflow are well-defined, extra bits are truncated.
Signed overflow with << is undefined. (Since C++14 it's well-defined if a resulting value is represenatble with an unsigned version of the left type. Then the tesult is converted back to signed.)
>> applied to signed negatives is implementation-defined. (Cppreference says that on most architectures it copies the leftmost bit.)
<< appled to signed negatives is undefined.
Those rules are same for C and C++. Here is a related part of C11 standard:
6.5.7 Bitwise shift operators
The integer promotions are performed on each of the operands. The type of the result is
that of the promoted left operand. If the value of the right operand is negative or is
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo
one more than the maximum value representable in the result type. If E1 has a signed
type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.
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 / 2E2. If E1 has a signed type and a negative value, the
resulting value is implementation-defined.

Large bitwise left shift on unsigned type

Is something like
uint32_t foo = 1;
foo = foo << 33;
undefined behaviour in C?
The shift is undefined behaviour in fact. See the standard (C11, final draft N1570, 6.5.7p3):
"... If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.".
Rationale: Shift operations can behave quite different on different CPU architectures if the shift count is >= the width of the argument. This way the standard allows the compiler to generate the fastest code without caring about border-effects.
Note: that things are different if int is wider than 33 bits (e.g. 64 bits). Reason are the integer promotions which first convert the uint32_t to int, so the shift is executed with the (then larger) int value. This leaves the back-conversion to uint32_t of the assignment, See 6.3.1.3, paragraph 1, 2 for this case. However, on most modern systems, int is not larger than 32 bits.
This is (apparently) undefined behaviour. From the C standard section 6.5.7 (of WG14/N1256 Committee Draft — Septermber 7, 2007 ISO/IEC 9899:TC3 - effectively the C99 standard):
The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
Re 3, this suggests it is undefined behaviour as the value of the right operand is greater or equal to the width of the promoted left operand.
Re 4, As the shift is unsigned, the first sentence applies: If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo one more than the maximum value representable in the result type. This would (but for 3) suggest result is therefore zero.
I believe 3 will take precedence over 4, so it is (after all) undefined.
Olaf's answer shows the same is true under C11.

Left shift of negative values by 0 positions?

In C, a left shift of a negative value is undefined behavior. I've encountered two libraries compiled with Intel's ICC where the offending code was removed. The same code was fine under Clang, Comeau, GCC and MSVC.
Does the standard make any mention of left shifting a negative value 0 places? Is it also undefined?
(The detail I'm curious about is a 0-sized shift, which is no shift at all in practice. So I'm wondering if the language is vague such that a 0-sized left shift may be allowed).
Excerpt from C99 with Technical corrigenda TC1, TC2, and TC3 included:
6.5.7 Bitwise shift operators
[...]
The integer promotions are performed on each of the operands. The type of the result is
that of the promoted left operand. If the value of the right operand is negative or is
greater than or equal to the width of the promoted left operand, the behavior is undefined.
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo
one more than the maximum value representable in the result type. If E1 has a signed
type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.
So, always undefined.

Is a >> ((sizeof a) * CHAR_BIT) Defined, UB or IDB?

1.
Consider the following:
unsigned int a, b;
b = a >> ((sizeof a) * CHAR_BIT);
/* or 2nd operand greater than ((sizeof a) * CHAR_BIT) */
Is this is defined, undefined behavior or implementation dependent behavior?
2.
Also another sub-question:
In the case a is signed int and it is shifted less than its bit length, is the signed bit shifting implementation defined or undefined behavior. In both the cases:
When shifting right : a >> 5
When shifting left : a << 5
EDIT question edited
1.
From C99 standard, section 6.5.7:
The integer promotions are performed on each of the operands. The type of the result is
that of the promoted left operand. If the value of the right operand is negative or is
greater than or equal to the width of the promoted left operand, the behavior is undefined.
So it's undefined.
2.
From the same section:
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 x 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 x 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
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 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
So for left-shift, it's well-defined if a is signed and positive. It's undefined if a is signed and negative.
For right-shift, it's well-defined if a is signed and positive. It's implementation-defined if a is signed and negative.

Resources