небольшая проблема битовой операции с unsigned int в сочетании с unsigned char - PullRequest
2 голосов
/ 22 февраля 2020

Привет, у меня возникла небольшая концептуальная проблема с битооперациями. Посмотрите код ниже, где у меня есть 4-байтовое без знака int. Затем я получаю доступ к отдельным байтам, присваивая адрес неподписанным символам.

Затем я устанавливаю значение последнего байта равным единице. И выполните сдвиг вправо на целое число без знака (переменная 4 байта). Я не понимаю, почему эта операция явно изменяет содержимое 3-х байтов.

См. Приведенный ниже код вместе с выводом при его запуске

#include <cstdio>

int main(int argc,char **argv){
  fprintf(stderr,"sizeof(unsigned int): %lu sizeof(unsigned char):%lu\n",sizeof(unsigned int),sizeof(unsigned char));
  unsigned int val=0;
  unsigned char *valc =(unsigned char*) &val;
  valc[3] = 1;
  fprintf(stderr,"uint: %u, uchars: %u %u %u %u\n",val,valc[0],valc[1],valc[2],valc[3]);
  val = val >>1;
  fprintf(stderr,"uint: %u, uchars: %u %u %u %u\n",val,valc[0],valc[1],valc[2],valc[3]);
  return 0;
}


sizeof(unsigned int): 4 sizeof(unsigned char):1
uint: 16777216, uchars: 0 0 0 1
uint: 8388608, uchars: 0 0 128 0

Заранее спасибо

Ответы [ 2 ]

4 голосов
/ 22 февраля 2020

Вы обнаружили, что ваш компьютер не всегда сохраняет байты для многобайтовых типов данных в порядке, который вы ожидаете. valc[0] - младший байт (LSB) в вашей системе. Поскольку LSB хранится по самому низкому адресу памяти, он известен как система с прямым порядком байтов. С другой стороны, valc[3] является самым значимым байтом (MSB).

Ваш вывод будет иметь больше смысла для вас, если вместо этого вы напечатаете valc[3],valc[2],valc[1],valc[0], так как люди ожидают, что наиболее значимые значения будут на left.

Другие компьютерные архитектуры являются "старшими байтами" и вначале будут хранить самый старший байт.

Эта статья также объясняет эту концепцию более подробно: https://en.wikipedia.org/wiki/Endianness

Книга Брайана Кернигана и Роба Пайка "Практика программирования" также содержит некоторые хорошие сведения о порядке байтов (раздел 8.6 Порядок байтов) и о том, как писать переносимые программы, которые работают как с big-endian, так и с системы с прямым порядком байтов.

2 голосов
/ 22 февраля 2020

Если мы изменим вывод int на hex (то есть изменим %u на %x), то, что произойдет, станет более очевидным:

uint: 1000000, uchars: 0 0 0 1
uint: 800000, uchars: 0 0 128 0

Значение из val сдвигается вправо на 1. Это приводит к смещению младшего бита старшего байта в старший бит следующего байта.

...