OR-ing octets en C # donne int [dupliquer]
-
06-07-2019 - |
Question
Cette question a déjà une réponse ici:
- décalage gauche 255 (sous forme d'octet) 7 réponses
J'ai ce code.
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (0x80 | dup) });
Lorsque j'essaie de compiler, je reçois:
Impossible de convertir implicitement le type 'int' à 'octet'. Une conversion explicite existe (il vous manque un casting?)
Pourquoi cela se produit-il? Ne devrait pas | deux octets donnent un octet? Les deux travaux suivants garantissent que chaque élément est un octet.
Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
La solution
C’est ce qui se fait de par la conception en C # et, en fait, remonte au C / C ++ - ce dernier promeut également les opérandes en int
, vous ne vous en rendez pas compte, car int -> char
la conversion effectuée implicite, alors que ce n'est pas en C #. Cela ne s'applique pas seulement à |
non plus, mais à tous les opérandes arithmétiques et au niveau des bits - par exemple. ajouter deux byte
vous donnera également un (byte)200 + (byte)100
. Je citerai la partie pertinente de la spécification ici:
Une promotion numérique binaire survient pour les opérandes du + prédéfini, & # 8211 ;, *, /,%, & amp ;, |, ^, ==,! =, > ;, < ;, > = et < = opérateurs binaires . Binaire promotion numérique convertit implicitement les deux opérandes à un type commun qui, en cas de non relationnel opérateurs, devient également le résultat type d'opération. Binaire numérique La promotion consiste à appliquer le règles suivantes, dans l’ordre dans lequel elles sont apparaissent ici:
Si l'un des opérandes est de tapez décimal, l'autre opérande est converti en type décimal, ou un erreur de compilation se produit si l'autre l'opérande est de type float ou double.
Sinon, si l'un des opérandes est de tapez double, l'autre opérande est converti en type double.
Sinon, si l'un des opérandes est de type float, l'autre opérande est converti en type float.
Sinon, si l'un des opérandes est de type ulong, l'autre opérande est converti en type ulong, ou un erreur de compilation se produit si l'autre l'opérande est de type sbyte, short, int, ou long.
Sinon, si soit l'opérande est de type long, l'autre l'opérande est converti en type long.
Sinon, si l'un des opérandes est de tapez uint et l'autre opérande est de tapez sbyte, short ou int, les deux les opérandes sont convertis en type long.
Sinon, si l'un des opérandes est de tapez uint, l'autre opérande est converti en type uint.
Sinon, les deux opérandes sont convertis en type int.
Je ne connais pas la raison exacte de cela, mais je peux en penser à un. Pour les opérateurs arithmétiques en particulier, il peut être un peu surprenant que les gens obtiennent 44
tout à coup l’équivalent de <=>, même si cela a du sens de considérer avec soin les types impliqués. Par contre, <=> est généralement considéré comme un type & "Suffisant" & "; pour l'arithmétique sur la plupart des nombres typiques, donc en promouvant les deux arguments en <=>, vous obtenez une sorte de & "tout fonctionne" & "; comportement dans les cas les plus courants.
Quant à savoir pourquoi cette logique a également été appliquée aux opérateurs au niveau des bits - j’imagine que c’est surtout pour des raisons de cohérence. Il en résulte une seule règle simple commune à tous les types binaires non booléens.
Mais tout cela est plutôt difficile à deviner. Eric Lippert serait probablement celui qui poserait au moins les raisons qui ont motivé cette décision pour C # (bien que ce serait un peu ennuyeux si la réponse est simplement & "C'est comme ça que ça se passe en C / C ++ et en Java, et c’est une règle assez bonne, alors nous n’avons vu aucune raison de la changer ").
Autres conseils
Le littéral 0x80 a le type " int " ;, de sorte que vous n'utilisez pas d'octets.
Le fait que vous puissiez le transmettre à l'octet [] ne fonctionne que parce que 0x80 (littéralement) se situe dans la plage d'octet.
Modifier : même si 0x80 est converti en octet, le code ne sera toujours pas compilé, car les octets oring donneront toujours int. Pour le compiler, le résultat de ou doit être converti: (byte)(0x80|dup)
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (byte)(0x80 | dup) });
Le résultat d'un bit au niveau des bits Ou (|) sur deux octets est toujours un entier.