2

Why this code prints two different numbers for f1 and f2?:

int main() {  
  int a = 32;
  int f1 = (0xffffffff << a); 
  int f2 = (0xffffffff << 32);

  std::cout << f1 << std::endl;  // print -1
  std::cout << f2 << std::endl;  // print 0
}

For f2, I get this warning but nothing for f1:

warning: left shift count >= width of type

I am using g++ 4.4.7

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
NaSh
  • 665
  • 5
  • 16
  • http://stackoverflow.com/questions/18918256/is-right-shift-undefined-behavior-if-the-count-is-larger-than-the-width-of-the-t/18918340#18918340 – ewcz Sep 21 '15 at 18:55

2 Answers2

2

The short answer would be you are invoking undefined behavior when shifting by width of type or greater.

The longer answer is that for the second case gcc can constant fold the expression and just moves in a zero (see it live on godbolt):

movl    $0, -28(%rbp)   #, f2

while in the first case it actually performs the shift:

movl    -20(%rbp), %eax # a, tmp63
movl    $-1, %edx   #, tmp64
movl    %edx, %ebx  # tmp64,
movl    %eax, %ecx  #,
sall    %cl, %ebx   #,
movl    %ebx, %eax  #, D.21248
movl    %eax, -24(%rbp) # D.21248, f1

Since we are invoking undefined behavior we can have no expectations for the result. Inconsistent answers to what seemingly should provide the same answer is perfectly acceptable undefined behavior.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
1

The result of

0xffffffff << 32

is

18446744069414584320

which is far larger then std::numeric_limits<int>::max()

If your system represents int as 4 bytes, then the above value is

2147483647 

Signed overflow is undefined behavior so both exhibit undefined behavior.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • 1
    op's asking why the behavior's different for the two versions, even though `a` is also 32. – Marc B Sep 21 '15 at 18:51
  • I expect to get 0 for both. for f2, it's correct, I get 0. But I get -1 for f1 which uses a instead of 32. – NaSh Sep 21 '15 at 18:53
  • 1
    @Nargesoo You should not *expect* anything, your code exhibits undefined behavior, so the result is unspecified. The fact that you consider an output of `0` to be "correct" doesn't agree with the C++ standard. – Cory Kramer Sep 21 '15 at 18:55
  • The result of the shift is undefined so we can't really talk about signed overflow here, this also does not explain the differing results. – Shafik Yaghmour Sep 21 '15 at 19:35