Сравнение символов с шестнадцатеричными значениями - PullRequest
5 голосов
/ 13 января 2012

В последний день в моем коде была неприятная ошибка, которая после некоторого поиска, похоже, связана со сравнением значений char и hex.Мой компилятор - gcc 4.4.1, работающий на Windows.Я повторил проблему в следующем простом коде:

char c1 = 0xFF; char c2 = 0xFE;
if(c1 == 0xFF && c2 == 0xFE)
{
    //do something
}

Удивительно, но приведенный выше код не попадает в цикл.Я понятия не имею, почему и был бы очень признателен за помощь в этом.Это настолько абсурдно, что решение должно быть (как всегда) огромной ошибкой с моей стороны, которую я полностью упустил из виду.

Если я заменю вышеприведенные символы без знака, это сработает, но только в некоторых случаях.Я изо всех сил пытаюсь выяснить, что происходит.Кроме того, если я приведу шестнадцатеричные значения к символу сравнения, он будет правильно введен в цикл:

if(c1 == (char)0xFF && c2 == (char)0xFE)
{
    //do something
}

Что это значит?Почему это может происходить?Разве необработанное шестнадцатеричное значение не интерпретируется как символ по умолчанию?Для любопытного момента в моем коде, где я впервые заметил, это сравнение первых 2-х байтов потока с вышеуказанным шестнадцатеричным значением и их обратная идентичность метке порядка байтов.

Любая помощь приветствуется

Ответы [ 5 ]

9 голосов
/ 13 января 2012

Обычный char может быть signed или unsigned.Если тип unsigned, то все работает так, как вы ожидаете.Если типом является signed, то присвоение 0xFF c1 означает, что значение будет повышено до -1 при выполнении сравнения, но 0xFF является обычным положительным целым числом, поэтому сравнение -1 == 0xFF не удается.

Обратите внимание, что типы char, signed char и unsigned char различны, но два из них имеют одинаковое представление (и один из двух char).

4 голосов
/ 29 ноября 2017

При сравнении символа с гексом вы должны быть осторожны:

Использование оператора == для сравнения символа с 0x80 всегда приводит к значению false?

Я бы порекомендовалэтот синтаксис введен в C99, чтобы быть уверенным

if(c1 == '\xFF' && c2 == '\xFE')
{
    // do something
}

Избегайте приведения, он не нужен и не безопасен для типов.

Он сообщает компилятору, что 0xFF - это символ, а не int, это решит вашу проблему.

clang compiler также предупредит вас об этом:

сравнение константы 128 с выражением типа 'char' всегда ложно [-Werror, -Wtautological-constantотъезда из диапазона Сравни]

4 голосов
/ 13 января 2012

Литерал 0xff - это не char, это int (подписано).Когда вы добавляете это значение в переменную char, она будет хорошо вписываться, но, в зависимости от того, будет ли тип char подписан или не подписан, это будет влиять на то, как оно обновляется в выражениях (см. Ниже).В таком выражении, как if (c1 == 0xff), переменная c1 будет преобразована в целое число, поскольку это 0xffто, на что он повышен, зависит от того, подписано оно или нет.

В итоге, вы можете сделать одно из двух:

  1. Убедитесь, чтовы используете signed char, чтобы он "расширялся" до правильного int.Под этим я подразумеваю, что беззнаковый символ 0xff станет (для 4-байтового int) 0x000000ff (так что все равно 255), но подписанный станет 0xffffffff (значит, -1).

  2. Вставьте литерал в тот же тип, что и переменная, которую вы уже делаете с (char)oxff.

0 голосов
/ 23 марта 2016

Я решил это, приведя мои переменные к UINT16 (оптимизирован для моего компилятора).В вашем случае вы будете разыгрывать c1 и c2 как INT

char c1 = 0xFF; char c2 = 0xFE;
if((int)c1 == 0xFF && (int)c2 == 0xFE)
{
    //do something
}
0 голосов
/ 13 января 2012

Символ 0xFE будет переведен в отрицательное целое число.Константы в выражении будут переведены в натуральные числа.

...