implicit type casting in JAVA

Tags:

자바에는 byte와 short를 위한 쉬프트 연산자가 없으며, 내부적으로 암시적인 캐스팅이 일어난다. 따라서 unsigned shift와 signed shift가 short, byte에 대해서는 제대로 동작하지 않으며 이것은 의도된 동작이라고 하는군요.

아 짜증나…..

이것때문에 엄청 헤멨음..

————————————————
Bug Id  4219016
 
Votes  0
 
Synopsis  Unexpected sign extension on >>> operator.
 
Category  java:runtime
 
Reported Against  1.2
 
Release Fixed   
 
State  Closed, will not be fixed
 
Related Bugs   
 
Submit Date  Mar 10, 1999 
 
Description  

Consider the code:
short value = (short)0x8000;
We know that shorts are 16-bit signed integers, so the cast is
necessary. The value of the variable is -32768.
What then do the following statements produce?
value >>= 1;
or
value >>>= 1;
You would think that the first would produce 0xC000 and the
second 0x4000. However, they both produce the same: 0xC000. This
is because the bitwise operators do not work with bytes or with
shorts. Instead, the system does an _implicit_ cast to integer
before doing the operation. So, converting -32768 to integer
gives 0xFFFF8000. Then, shifting this value to the right gives
0xFFFFC000 or 0x7FFFC000, in the non-sign-extending case. Then,
after the operation, the value is again _implicitly_ cast back
to short! This truncates the high-order bits, giving identical
results. This is despite the promise of the “>>>” operator not
to sign extend! This is an amazingly subtle bug.

It could be easily corrected by working with the type specified,
instead of doing the unintuitive implicit cast to integer.

Please contact me and let me know what you think.
Thanks,
Joe Preston
Agent Systems, Inc.
Carrollton, TX
972-774-0477
xxxxx@xxxxx
(Review ID: 53704)

 
Workaround  

My only workaround is to do the following:

value = (short)(((int)value & 0xffff) >> 1);

 
Evaluation  This is as specified.  There are no opcodes for shifting shorts or bytes.

xxxxx@xxxxx 1999-03-18

 
————————————-

Bug Id  4090916
 
Votes  0
 
Synopsis  >>> does not do 0 extension of -ive numbers (is same as >>)
 
Category  java:runtime
 
Reported Against  1.1.4
 
Release Fixed   
 
State  Closed, not a bug
 
Related Bugs   
 
Submit Date  Nov 05, 1997 
 
Description  

Try this c program – it allows the >> operator to work in two separate
ways:

This is done by having signed and unsigned numbers in c.  The shifting
produces different results although starting with the SAME bit pattern
in either the signed or unsigned case

The equivalent in Java is to fill the byte (same size as c char,) with
the value required, and when shifting, the byte is treated as the
equivalent of c signed for >>, and as c unsigned for >>>.

Actually it should be, except that the >>> operator does the same as
the >>, and hence this is a MAJOR bug – i.e. it is a fundamental
operator that is implemented incorrectly, not some little used class.

c-program
/**********************************/
#include <stdio.h>

void main(int argc, char **argv)
{
  int shifted2signed, shifted2unsigned;
  signed char signedchar;
  unsigned char unsignedchar;

  printf(“ALTHOUGH SIGNED AND UNSIGNED FULL CONTAIN THE SAME
VALUE\n”);
  printf(“ORIGINALLY, THE >>operator FILLS SIGNED WITH WHATEVER THE
TOP\n”);
  printf(“BIT IS, THE UNSIGNED VERSION IS FILLED WITH ZEROS IN
BIT\n”);
  printf(“EIGHT\n\n”);

  printf(“IN JAVA THERE ARENT SIGNED AND UNSIGNED VERSIONS, SO THEY
HAVE\n”);
  printf(“>> and >>> operators, BUT >>> does the same as >>, WHICH IS
NO USE\n\n”);

  printf(“SIGNED SHIFT = >>, UNSIGNED SHIFT = >>> in Java\n\n”);

  /*******************************/
  printf(“FOR A NUMBER WITH LEADING 1:\n”);
  printf(“8 bits = 11110000 originally\n\n”);

  signedchar = (char)0xF0; //=-16, shifted = -4
  unsignedchar = (char)0xF0; //=240, shifted = 60

  printf(“signedchar is %d\t unsignedchar is %d\n”, signedchar,
unsignedchar);

  shifted2signed = (signedchar >> 2);
  shifted2unsigned = (unsignedchar >> 2);

  printf(“shifted 2 = %d\t\t shifted 2 = %d\n”, shifted2signed,
shifted2unsigned);
  printf(“8bits now = 11111100\t 8bits now = 00111100\n\n”);

  /********************************/
  printf(“FOR A NUMBER WITH LEADING 0:\n”);
  printf(“8 bits = 00001000 originally\n\n”);

  signedchar = (char)0x08; //=8 shifted = 2
  unsignedchar = (char)0x08; //=8 shifted = 2

  printf(“signedchar is %d\t unsignedchar is %d\n”, signedchar,
unsignedchar);
  shifted2signed = (signedchar >> 2);
  shifted2unsigned = (unsignedchar >> 2);
  printf(“shifted 2 = %d\t\t shifted 2 = %d\n”, shifted2signed,
shifted2unsigned);
  printf(“8bits now = 00000010\t 8bits now = 00000010\n\n”);
}
/*********************************/
end-of-c-program

To try the equivalent in java just compile this class, and run it.

public class shift
{
  public static void main (String[] args)
  {
    byte beginsWithOne = (byte)0xF0;
    byte beginsWithZero = (byte)0x08;

    System.out.println(“11110000 >> 2 = ” +
(byte)(beginsWithOne>>2));
    System.out.println(“should be 11111100 = -4\n”);

    System.out.println(“11110000 >>> 2 = ” +
(byte)(beginsWithOne>>>2));
    System.out.println(“should be 00111100 = 60\n”);

    System.out.println(“00001000 >> 2 = ” +
(byte)(beginsWithZero>>2));
    System.out.println(“should be 00000010 = 2\n”);
    System.out.println(“00001000 >>> 2 = ” +
(byte)(beginsWithZero>>>2));
    System.out.println(“should be 00000010 = 2\n”);

    System.out.println(“\nAs can be seen, the >>> operator = >>
operator – BUG”);
  }
}

(Review ID: 19507)

 
Workaround  

//to get the required result
//have to unset top bit, shift, then reset bit
//in correct place
//same for int – I’m just using byte at the moment

byte fix = (byte)(((full & 0x7F) >>> 2) | 0x60);

 
Evaluation  This is what JLS says things should work. Arguments are promoted to 32-bit
integers.

xxxxx@xxxxx 1997-11-14

 

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *