5

I am trying to right shift an integer by 32 but the result is the same number. (e.g. 5 >> 32 is 5.)

If I try to do same operation on Byte and Short it works. For example, "(byte)5 >> 8" is 0.

What is wrong with Integer?

Ricardo Cristian Ramirez
  • 1,194
  • 3
  • 20
  • 42
  • 3
    Byte is 8 bit and short is 16 bit but why they work? – Ricardo Cristian Ramirez Sep 18 '15 at 09:11
  • 4
    can this help? http://stackoverflow.com/questions/1023373/findbugs-warning-integer-shift-by-32-what-does-it-mean – yelliver Sep 18 '15 at 09:16
  • @TheLostMind Although that is true from the perspective of the JLS, shifting is not the same as a rotate which your comment seems to imply. – Mark Rotteveel Sep 18 '15 at 09:37
  • 1
    @MarkRotteveel totally agree. That java wraps its shift amount is an annoying bug in the language. I.e. shifting 8 bit behaves as shifting 32 bit, but shifting 64 bit suddenly differs... wtf were they smoking? – BeyelerStudios Sep 18 '15 at 10:00

2 Answers2

12

JLS 15.19. Shift Operators

... If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance.

so shifting 32 is not effective.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • 2
    This is the real answer. The OP's code behaves that way (fundamentally) because the Java Language Specification says it **must**. – Stephen C Sep 18 '15 at 09:25
1

A Shifting conversion returns result as an int or long. So, even if you shift a byte, you will get an int back.

Java code :

public static void main(String s[]) {
    byte b = 5;
    System.out.println(b >> 8);
    int i = 8;
    System.out.println(i >> 32);
}

Byte code :

         0: iconst_5
         1: istore_1
         2: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream; 
         5: iload_1
         6: bipush        8
         8: ishr
         9: invokevirtual #22      // Method java/io/PrintStream.println:(I)V  ==> Using println(int)
        12: bipush        8
        14: istore_2
        15: getstatic     #16     // Field java/lang/System.out:Ljava/io/PrintStream;
        18: iload_2
        19: bipush        32
        21: ishr
        22: invokevirtual #22      // Method java/io/PrintStream.println:(I)V   ==> Using println(int)
        25: return
TheLostMind
  • 35,966
  • 12
  • 68
  • 104
  • @Codebender - I didn't say that it was *circular* – TheLostMind Sep 18 '15 at 09:23
  • 1) Disassembling bytecodes is only helpful for people who can read them fluently. That is probably less than 5% of Java programmers. 2) It only shows what a particular compiler generates. Who is to say if the compiler has got it right? Or if there may be other bytecode sequences that behave differently and are also "right"? – Stephen C Sep 18 '15 at 09:23
  • 2
    @StephenC - I chose to un-delete this answer despite of numerous downvotes because byte-code provides valuable info here. All shifts result in either int or long. Shifting `byte` still results in an `int`. – TheLostMind Sep 18 '15 at 09:27
  • @Codebender - It was like explaining it in *layman's terms*. Shift is not circular. – TheLostMind Sep 18 '15 at 09:30
  • 3
    That is your opinion. My opinion is that the bytecodes don't prove anything. And they provide the information in an obfuscated fashion. See my comments above. This applies to just about any answer to a Java question that includes disassembled bytecodes. It is a really poor way of conveying information to human beings, and especially to novice Java programmers. – Stephen C Sep 18 '15 at 09:31
  • 1
    @StephenC -I agree. I find it easier to check byte code and come to conclusions (which is perhaps wrong sometimes :P) instead of looking for proper jls sections – TheLostMind Sep 18 '15 at 09:32
  • 2
    Yes ... the JLS spec is the right place to go for a definitive answer. And if you are saying that bytecode dumps are a lazy way to answer ... I agree with that too :-) – Stephen C Sep 18 '15 at 09:32
  • thx. this is the first time i've read disassembled bytecode. it was totally helpful. so it seems that method local variables "byte b=5" and "int b=5" would even generate nearly the same bytecode (in this example), no conversion is happening at runtime. "iconst_5" and "bipush 8" are the only difference. i assume that would be optimized in the next compiler step. – comonad Oct 20 '22 at 12:10