Интерпретировать шестнадцатеричные значения? - PullRequest
8 голосов
/ 04 декабря 2010

Это может быть очень просто или даже глупо для экспертов здесь, но я хотел обдумать это.В большинстве случаев я обычно пишу шестнадцатеричные значения, подобные этому, в C:

unsigned int a = 0xFFFF1232;

Допустим, я пытаюсь извлечь первый и последний 16-битный код, тогда я могу просто сделать:

unsigned short high = a >> 16; // Gives me 0xFFFF
unsigned short low = a & 0x0000FFFF; // Gives me 0x00001232 which is then stored as 0x1232

В некотором коде, который я читаю, я встретил следующее:

unsigned short high = a >> 16; 
unsigned short low = a & 0xFFFF; 

У меня есть два вопроса

  • Когда вы AND используете 32-битную версиюзначение с маской, почему люди пишут 0xFFFF вместо 0x0000FFFF?Чтобы сохранить его компактным?
  • Всегда ли безопасно писать 0x0000FFFF как 0xFFFF?По-разному ли оно интерпретируется в каком-либо контексте?

Ответы [ 5 ]

7 голосов
/ 04 декабря 2010

Они полностью синонимы. Отсутствие лидирующих нулей делает его немного более читабельным.

3 голосов
/ 04 декабря 2010

Они идентичны.

И вы делаете предположение, что целые числа всегда имеют длину 32 бита.Если бы ваша платформа использовала 64-битные целые числа, вы бы написали это так?

 unsigned short low = a & 0x000000000000FFFF; // ouch. Did I count them right?

И есть еще одна причина, почему вы не должны тратить время на ввод первых нулей: вы попробуете это сделать сследующий десятичный знак, что является плохой идеей:

int x = 00000377

printf("%d\n", x); // 255! WTF....
2 голосов
/ 04 декабря 2010

В вашем примере low - это short (обычно 16 бит). Таким образом, начальные нули не только избыточны, они предполагают, что ожидается 32-битный результат, и в этом случае старшие биты отбрасываются, поэтому, возможно, это делает цель кода более понятной.

На самом деле в этом случае

unsigned short low = a ;

будет достаточно, хотя, возможно, менее ясно.

Кроме того, вы не должны предполагать, что целочисленная ширина является подходящей, и вместо этого используйте типы <stdint.h>:

uint32_t a = 0xFFFF1232;
uint16_t = a >> 16; 
uint16_t = a & 0xFFFF; 

Если вы используете VC ++, который не предоставляет этот заголовок, вы можете использовать эту реализацию

1 голос
/ 04 декабря 2010

В вашем случае 0x0000FFFF и 0xFFFF идентичны.

Это не так, если ваши переменные не были беззнаковыми: 16-битное значение 0xFFFF означает -1, что равно 0xFFFFFFFF в 32 битах.

1 голос
/ 04 декабря 2010

Нечто подобное 0x1 называется литералом, по умолчанию это тип int. Это не обязательно 32 бита, в зависимости от компилятора или платформы, так что да, есть контекст, в котором небезопасно оставлять начальные нули.

Например, во встроенных системах обычно встречаются типы int длиной всего 16 бит. Если вам нужно более длинное целое число, вам нужно использовать long int.

В этом случае компилятор заметит, если вы забыли добавить «L» к шестнадцатеричному литералу, чтобы указать, что вы хотите более длинный тип.

unsigned int a = 0xFFFF1234;

в лучшем случае будет ошибкой компилятора или в худшем случае необнаруженной ошибкой. Вам нужно будет использовать

unsigned long int a = 0xFFFF1234L;

вместо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...