簡體   English   中英

使用按位包含OR的錯誤結果

[英]Wrong result with bitwise inclusive OR

我無法弄清楚為什么包容性OR會返回錯誤的結果。

char arr[] = { 0x0a, 0xc0 };
uint16_t n{};

n = arr[0]; // I get 0x000a here.
n = n << 8; // Shift to the left and get 0x0a00 here.
n = n | arr[1]; // But now the n value is 0xffc0 instead of 0x0ac0.

這個例子中的錯誤是什么? 控制台應用程序,MVS社區2017。

意外的0xff是由符號位擴展 0xc0引起的。

0xc0 = 0b11000000

因此,最高位被設置,這意味着對char進行signed char (作為signed char )。

請注意,C ++中的所有算術和按位運算至少使用int (或unsigned int )。 較小的類型在之前被提升並且之后被剪輯。

請注意, char可以是簽名或未簽名。 這是依賴於編譯器的實現。 顯然,它是在OP的情況下簽署的。 為防止意外的符號擴展,參數必須變為無符號(足夠早)。

示范:

#include <iostream>

int main()
{
  char arr[] = { '\x0a', '\xc0' };
  uint16_t n{};

  n = arr[0]; // I get 0x000a here.
  n = n << 8; // Shift to the left and get 0x0a00 here.
  n = n | arr[1]; // But now the n value is 0xffc0 instead of 0x0ac0.
  std::cout << std::hex << "n (wrong): " << n << std::endl;
  n = arr[0]; // I get 0x000a here.
  n = n << 8; // Shift to the left and get 0x0a00 here.
  n = n | (unsigned char)arr[1]; // (unsigned char) prevents sign extension
  std::cout << std::hex << "n (right): " << n << std::endl;
  return 0;

}

會議:

g++ -std=c++11 -O2 -Wall -pthread main.cpp && ./a.out
n (wrong): ffc0
n (right): ac0

coliru的生活演示

注意:

我不得不改變
char arr[] = { 0x0a, 0xc0 };

char arr[] = { '\\x0a', '\\xc0' };
來到嚴重的編譯器投訴。 我猜,這些投訴與這個問題密切相關。

您已成為簽名整數促銷的受害者。

0xc0分配給數組中的第二個元素(由於MVS而簽名的char默認值)時,其表示如下:

arr[1] = 1100 - 0000, or in decimal -64

當它轉換為uint16_t ,它將被提升為值為-64的整數。 這是:

n = 1111 - 1111 - 1100 - 0000 = -64  

由於2的補碼實現整數。

因此:

n          = 1111 - 1111 - 1100 - 0000 
arr[1]     = 0000 - 0000 - 1010 - 0000 (after being promoted)

n | arr[1] = 1111 - 1111 -1110-0000 = 0xffc0

通過這樣做我讓它正常工作:

int arr[] = { 0x0a, 0xc0 };
int n{};

n = arr[0]; // I get 0x000a here.
n = n << 8; // Shift to the left and get 0x0a00 here.
n = n | arr[1];
std::cout << n << std::endl;

如果將'arr'數組保留為char,則會發生一些截斷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM