Que fait value & 0xff en Java?

98

J'ai le code Java suivant:

byte value = 0xfe; // corresponds to -2 (signed) and 254 (unsigned)
int result = value & 0xff;

Le résultat est 254 une fois imprimé, mais je n'ai aucune idée du fonctionnement de ce code. Si l' &opérateur est simplement au niveau du bit, alors pourquoi ne produit-il pas un octet et plutôt un entier?

dagronlund
la source
Je copie le code sur Eclipse. Il m'avertit "Incompatibilité de type: impossible de convertir un entier en octet". Devrait-il changer en valeur int = 0xfe;
Ben Cheng
1
@BenCheng devrait êtrebyte value = (byte) 0xfe;
Bek

Réponses:

171

Il définit resultla valeur (non signée) résultant de la mise des 8 bits de valuedans les 8 bits les plus bas de result.

La raison pour laquelle quelque chose comme cela est nécessaire est qu'il bytes'agit d'un type signé en Java. Si vous venez d'écrire:

int result = value;

alors resultfinirait avec la valeur ff ff ff feau lieu de 00 00 00 fe. Une autre subtilité est que le &est défini pour n'opérer que sur les intvaleurs 1 , donc ce qui se passe est:

  1. valueest promu en int( ff ff ff fe).
  2. 0xffest un intlittéral ( 00 00 00 ff).
  3. Le &est appliqué pour donner la valeur souhaitée pour result.

(Le fait est que la conversion se intproduit avant que l' &opérateur ne soit appliqué.)

1 Eh bien, pas tout à fait. L' &opérateur travaille également sur les longvaleurs, si l'un des opérandes est un long. Mais pas sur byte. Voir la spécification du langage Java, sections 15.22.1 et 5.6.2 .

Ted Hopp
la source
Que signifie le x dans cette notation? x n'est pas un nombre ou un nombre hexadécimal?
Callat
3
@KazRodgers - Le préfixe 0x(ou 0X) indique à Java que le littéral entier qui suit doit être interprété comme hex (base 16). Java prend également en charge un 0préfixe nu pour les littéraux octaux et un préfixe 0b(ou 0B) pour les littéraux binaires. Consultez la spécification du langage Java pour plus d'informations sur les littéraux entiers.
Ted Hopp
Le littéral qui suit? Donc, par exemple, si j'avais 0x3fa. Le 3fa est la partie en cours de traduction en un nombre littéral et 0x note "ceci est un nombre hexadécimal"? @TedHopp?
Callat
1
@KazRodgers - Exactement. Notez que 0xou 0bpar lui-même (sans aucun chiffre) est une syntaxe illégale en Java.
Ted Hopp
1
@DmitryMinkovsky - Le motif de bits hexadécimaux feen 8 bits, le complément à deux correspond à la valeur décimale -2. Pour conserver la valeur, Integer.valueOf(byte)il faudrait produire ff ff ff fe(−2 en 32 bits, complément à deux), pas 00 00 00 fe(valeur décimale 254). Cette transformation (d'une bytevaleur feà une intvaleur ff ff ff fe) est connue sous le nom d'extension de signe et fait partie de la spécification du langage Java. Le but de value & 0xffest d'annuler l'extension de signe (c'est-à-dire de simuler une extension nulle, ce que Java n'a pas).
Ted Hopp
57

De http://www.coderanch.com/t/236675/java-programmer-SCJP/certification/xff

Le littéral hexadécimal 0xFF est un entier égal (255). Java représente int comme 32 bits. Cela ressemble à ceci en binaire:

00000000 00000000 00000000 11111111

Quand vous faites un peu sage ET avec cette valeur (255) sur n'importe quel nombre, cela va masquer (faire des ZERO) tous sauf les 8 bits les plus bas du nombre (seront tels quels).

... 01100100 00000101 & ...00000000 11111111 = 00000000 00000101

& est quelque chose comme% mais pas vraiment .

Et pourquoi 0xff? ceci dans ((puissance de 2) - 1). Tout ((puissance de 2) - 1) (par exemple 7, 255 ...) se comportera quelque chose comme l'opérateur%.

Alors
en binaire, 0 est, tous les zéros, et 255 ressemble à ceci:

00000000 00000000 00000000 11111111

Et -1 ressemble à ceci

11111111 11111111 11111111 11111111

Lorsque vous effectuez un ET au niveau du bit de 0xFF et toute valeur comprise entre 0 et 255, le résultat est exactement le même que la valeur. Et si une valeur supérieure à 255 reste, le résultat sera compris entre 0 et 255.

Cependant, si vous faites:

-1 & 0xFF

vous obtenez

00000000 00000000 00000000 11111111, qui ne correspond PAS à la valeur d'origine de -1 ( 11111111soit 255 en décimal).


Quelques manipulations de bits supplémentaires: (sans rapport avec la question)

X >> 1 = X/2
X << 1 = 2X

Vérifiez qu'un bit particulier est défini (1) ou non (0) puis

 int thirdBitTobeChecked =   1 << 2   (...0000100)
 int onWhichThisHasTobeTested = 5     (.......101)

 int isBitSet = onWhichThisHasTobeTested  & thirdBitTobeChecked;
 if(isBitSet > 0) {
  //Third Bit is set to 1 
 } 

Définir (1) un bit particulier

 int thirdBitTobeSet =   1 << 2    (...0000100)
 int onWhichThisHasTobeSet = 2     (.......010)
 onWhichThisHasTobeSet |= thirdBitTobeSet;

ReSet (0) un bit particulier

int thirdBitTobeReSet =   ~(1 << 2)  ; //(...1111011)
int onWhichThisHasTobeReSet = 6      ;//(.....000110)
onWhichThisHasTobeReSet &= thirdBitTobeReSet;

XOR

Notez simplement que si vous effectuez l'opération XOR deux fois, la même valeur sera obtenue.

byte toBeEncrypted = 0010 0110
byte salt          = 0100 1011

byte encryptedVal  =  toBeEncrypted ^ salt == 0110 1101
byte decryptedVal  =  encryptedVal  ^ salt == 0010 0110 == toBeEncrypted :)

Une autre logique avec XOR est

if     A (XOR) B == C (salt)
then   C (XOR) B == A
       C (XOR) A == B

Ce qui précède est utile pour permuter deux variables sans température comme ci-dessous

a = a ^ b; b = a ^ b; a = a ^ b;

OU

a ^= b ^= a ^= b;
Kanagavelu Sugumar
la source
Regardez aussi @ Bit manipulation stackoverflow.com/questions/13422259/…
Kanagavelu Sugumar
4

Cela aide à réduire beaucoup de codes. Il est parfois utilisé dans les valeurs RVB constituées de 8 bits.

où 0xff signifie 24 (0) et 8 (1) comme00000000 00000000 00000000 11111111

Il masque efficacement la variable de sorte qu'il ne laisse que la valeur dans les 8 derniers bits et ignore tout le reste des bits

Cela se voit le plus souvent dans des cas comme lors de la tentative de transformation des valeurs de couleur d'un format spécial en valeurs RVB standard (d'une longueur de 8 bits).

Grande explication Voir ici

AndroidGeek
la source
0

Dans le système au format 32 bits, la valeur hexadécimale 0xffreprésente ce 00000000000000000000000011111111qui est 255(15*16^1+15*16^0)en décimal. et l'opérateur binaire & masque les 8 mêmes bits les plus à droite que dans le premier opérande.

manish kumar
la source
pouvez-vous expliquer un peu plus.
ashishdhiman2007