-1
int main(){
    ll a=pow(2,32);
    cout <<a<<endl;
    cout << (-1<<1)<<endl;
    printf("%x",-1<<1);
}

For the above code, I am getting following output:

4294967296
-2
fffffffe

4294967296 in decimal is equal to fffffffe in hexadecimal which is basically 2^32. Why is printf and cout behaving differently? And how exactly does this shift works?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
rishiag
  • 2,248
  • 9
  • 32
  • 57
  • Try `printf("%d", ...)` instead. – alk Oct 25 '13 at 14:44
  • 2
    4294967296 is most certainly not equal to fffffffe. The former is `2^32`, the latter is `2^32-2`. – Robᵩ Oct 25 '13 at 14:49
  • There is a difference of interpretation as to whether left shifting a negative number is *undefined* or not. John created a [question](http://stackoverflow.com/questions/19593938/is-left-shifting-a-negative-integer-undefined-behavior-in-c11) to see if we can resolve it. – Shafik Yaghmour Oct 25 '13 at 16:18

8 Answers8

4

The printf format flag %x means to print an integral value in hexadecimal.

There is a stream manipulator to accomplish this as well (std::hex), but you're not using that. When you output an integral value to a stream with no manipulators, it outputs in base 10.

See here for more information about the printf format flags, and here for information about stream manipulators.

The shift operator << works as described in the C++03 Standard (14882:2003):

5.8 Shift operators

1/ The shift operators << and >> group left-to-right. shift-expression: additive-expression shift-expression << additive-expression shift-expression >> additive-expression

The operands shall be of integral or enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

2/ The value of E1 << E2 is E1 (interpreted as a bit pattern) left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 multiplied by the quantity 2 raised to the power E2, reduced modulo ULONG_MAX+1 if E1 has type unsigned long, UINT_MAX+1 otherwise.

[Note: the constants ULONG_MAX and UINT_MAX are defined in the header ). ]

In your case, the value -1 in binary is all 1s in every bit. For a 32 bit value, then:

11111111 11111111 11111111 11111111 

If you shift this left 1 bit using <<, you get:

11111111 11111111 11111111 11111110 

Which in base 10 is -2. Since the operation -1<<1 uses a negative number for the LHS, the entire expression is of a signed (not unsigned) type.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • But Why it is printing "-2" in case of cout? Shouldn't it print "4294967296"? I am asking how come the two values are different. I understand the difference between hexadecimal and decimal representation. – rishiag Oct 25 '13 at 14:49
  • @JohnDibling You only need 32-bits to show `-1 << 1` as they are both `int`s and not `long long`s. – Zac Howland Oct 25 '13 at 15:02
  • @ZacHowland: I know, but the OP's code used `ll` as a type declaration for `a`, which I guessed meant `uint64_t`. – John Dibling Oct 25 '13 at 15:03
  • @JohnDibling For `a`, yes. Everything he did after that was dealing with 32-bit `int`s though (which is a big part of his overall problem). – Zac Howland Oct 25 '13 at 15:06
  • @ZacHowland: I suppose you're right. I made then 32 bit values. – John Dibling Oct 25 '13 at 15:07
1

First,

fffffffe in hexadecimal which is basically 2^32

is wrong. FFFFFFFE = 4294967294, which is 2^32 - 2 (for unsigned integers), or -2 (for 32-bit signed integers in 2's complement).

Second, printf("%x", ...) will print an unsigned hexadecimal integer (that is an unsigned int), which is 32-bits on most modern systems. long long a = 2 << 32 requires a 64-bit integer to properly store it (or, more precisely, at least a 33-bit integer), so when you use cout << a, you are calling ostream& operator<<(ostream&, long long), which has the proper type. That is, you are running into an overflow issue because of the type used by the printf specifier vs the strong type used by the C++ operator<< overload.

Zac Howland
  • 15,777
  • 1
  • 26
  • 42
1

This code invokes undefined behavior since you are trying to left shift a negative number, the draft C++11 Standard section 5.8 Shift operators says(emphasis mine):

The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. 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. Otherwise, if E1 has a signed type and non-negative value, and E1×2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

This is also the same for the draft C99 standard section 6.5.7 Bitwise shift operators

It is also undefined behavior to specify an invalid conversion specifier to printf, you are specifying %x which expect an unsigned int but the result is signed. The C99 draft in section 7.19.6.1 The fprintf function paragraph 9 says:

If a conversion specification is invalid, the behavior is undefined.248) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • `E1` here does not have non-negative value. Also, this does not match the Standard I wuoted (C++03) – John Dibling Oct 25 '13 at 15:06
  • @JohnDibling This is `n3485` so as far as I remember the language has changed from `03`. Right so the quote says `E1` is non-negative then it is defined as otherwise it is undefined which fits this case. – Shafik Yaghmour Oct 25 '13 at 15:07
  • Edited your post to include the text from the published Standard, rather than the draft. There are some differences. – John Dibling Oct 25 '13 at 15:13
  • So, are you interpreting this to mean that left-shifting a negative number results in Undefined Behavior? – John Dibling Oct 25 '13 at 15:13
  • Did you intentionally (effectively) roll back my edits and go back to the draft standard? – John Dibling Oct 25 '13 at 15:17
  • @JohnDibling I was in the middle of another edit and did not see your comment. Regardless I would be reluctant to quote what I don't have in front of me. – Shafik Yaghmour Oct 25 '13 at 15:19
  • I did not vandalize your answer. – John Dibling Oct 25 '13 at 15:21
  • @JohnDibling Not suggesting you did, I know that your intentions were only to improve the answer. – Shafik Yaghmour Oct 25 '13 at 15:21
  • @JohnDibling Also the latest draft C++ standard has very similar language, I usually pick them up from [this](http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents) thread and so I feel comfortable using this quote. – Shafik Yaghmour Oct 25 '13 at 15:30
  • Back to an earlier question: are you interpreting this to mean that left-shifting a negative number results in Undefined Behavior? – John Dibling Oct 25 '13 at 15:31
  • Also, take a look here: http://stackoverflow.com/questions/19593938/is-left-shifting-a-negative-integer-undefined-behavior-in-c11 – John Dibling Oct 25 '13 at 15:32
  • @JohnDibling It sure reads to me that it is undefined but I am willing to be convinced otherwise. Let's see what answers your questions receives. – Shafik Yaghmour Oct 25 '13 at 15:34
  • I can totally see how you would interpret it that way, but I interpreted it the other way. Let's see what happens. – John Dibling Oct 25 '13 at 15:35
  • @JohnDibling So it seems like the consensus is that it is indeed *undefined*, doubt I will get the up vote back but at least I learned something interesting. – Shafik Yaghmour Oct 25 '13 at 19:39
  • Well, I'll give you one instead. – John Dibling Oct 25 '13 at 19:43
0

%x formats the output to show the value in hexadecimal, so you should pass std::hex to cout to do a same thing:

std::cout << std:::hex << (-1<<1) << endl;
             ^^^^^^^^^
masoud
  • 55,379
  • 16
  • 141
  • 208
0

This will produce the correct same answer as you need to tell it to print in hex

cout << hex<<(-1<<1)<<endl;
printf("%x",-1<<1);
kunal
  • 956
  • 9
  • 16
0

%x is hex where as the cout are just outputting the numbers (int) directly -1 is 0xFFFFFFFF shift that to the left you have to add in a 0 ie so the last F (in binary is 1111 becomes 1110 ie E The other guys answer your points clearer I think....

Angus Connell
  • 419
  • 3
  • 6
0

For the sake of readbility let's use a signed 8bit integer:

-1 bitwise is 11111111

now doing a left-shift by 1:

-1 << 1

you get:

11111110 which is -2

However using the the conversion specifier %x tells printf() to tread 11111111 as un-signed so it prints out fe.

alk
  • 69,737
  • 10
  • 105
  • 255
0

The first case is valid: pow(2,32) returns the exact value 232 as a double, which remains exact when you convert it to long long (I'm assuming that's what the mystery ll type is). Printing this with cout is perfectly valid.

In the case of (-1<<1), left-shifting a negative number yields undefined behavior. Even if the compiler does define it as -2 (most will), it's also undefined behavior to pass a negative number for use with printf's %x specifier (which requires an unsigned type).

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711