Встроенный C: что такое var = 0xFF; делать? - PullRequest
19 голосов
/ 13 октября 2008

Я работаю со встроенным Си в первый раз. Хотя мой C ржавый, я могу прочитать код, но я не совсем понимаю, почему определенные строки таковы. Например, я хочу знать, является ли переменная истинным или ложным, и отправить ее обратно в другое приложение. Вместо того, чтобы устанавливать переменную в 1 или 0, оригинальный разработчик выбрал 0xFF.

Он пытается установить его в адресное пространство? или иначе зачем устанавливать логическую переменную равной 255?

Ответы [ 9 ]

31 голосов
/ 13 октября 2008

0xFF устанавливает все биты в символе.

Исходный разработчик, вероятно, решил, что стандартные 0 и 1 недостаточно хороши, и решил, что если все биты off равны false , то все биты равно верно .

Это работает, потому что в C любое значение, кроме 0, является истинным. Хотя это установит все байты в символе, оно также будет работать для любого другого типа переменной, поскольку любой бит, установленный в переменной, делает его истинным.

12 голосов
/ 13 октября 2008

Если вам отчаянно требуется память, вы можете хранить 8 логических значений в одном байте (или 32 в длинном, или как угодно)

Это легко сделать с помощью маски флага:

  // FLAGMASK = ..1<<n for n in 0..7...
  FLAGMASK = 0x10;    // e.g. n=4

  flags &= ~FLAGMASK; // clear bit
  flags |= FLAGMASK;  // set bit
  flags ^= FLAGMASK;  // flip bit
  flags = (flags & ~FLAGMASK) | (booleanFunction() & FLAGMASK); // clear, then maybe set

это работает только тогда, когда booleanFunction () возвращает 0 (все биты очищены) или -1 (все биты установлены).

9 голосов
/ 26 октября 2012

Эти молодые ребята, что они знают?

В одном из оригинальных встроенных языков - PL / M (-51 да как в 8051, -85, -86, -286, -386) - не было никакой разницы между логическими операторами (!, &&, || в В) и поразрядно (~, &, |, ^). Вместо этого PL / M имеет NOT, AND, OR и XOR, заботящиеся об обеих категориях. Нам лучше с двумя категориями? Я не уверен. Я скучаю по логическому оператору ^^ (xor) в C, хотя. Тем не менее, я предполагаю, что было бы возможно создавать программы на C без использования логической категории.

В PL / M False определяется как 0. Логические значения обычно представлены в байтовых переменных. True определяется как NOT False, что даст вам 0ffh (PL / M-ese для C's 0xff).

Чтобы увидеть, как происходило преобразование переноса флага состояния перед сохранением в байтовой переменной (булево значение не было доступно как тип), PL / M мог использовать инструкцию по сборке "sbb al, al" перед сохранением. Если было установлено значение carry, al будет содержать 0ff, если нет, то будет 0h. Если требуется противоположное значение, PL / M вставит «cmc» перед sbb или добавит «not al» после (на самом деле xor - один или другой).

Таким образом, 0xff для TRUE - это порт прямой совместимости от PL / M. Необходимо? Вероятно, нет, если вы не уверены в своих навыках (в C) И не играете в них супер-безопасно.

Как я бы.

PL / M-80 (используемый для 8080, 8085 и Z80) не имел поддержки целых чисел или чисел с плавающей запятой, и я подозреваю, что это было то же самое для PL / M-51. В PL / M-86 (используется для 8086, 8088, 80188 и 80186) добавлены целые числа, с плавающей запятой одинарной точности, указатели сегмента: смещение и стандартные модели памяти малого, среднего, компактного и большого размера. Для тех, кто был склонен к этому, были специальные директивы для создания гибридных моделей памяти «сделай сам». Огромная модель памяти Microsoft была эквивалентна большой Intel. MS также носила крошечные, маленькие, компактные, средние и большие модели.

9 голосов
/ 13 октября 2008

0xFF - это шестнадцатеричное представление ~ 0 (т.е. 11111111)

В, например, VB и Access, -1 используется как True.

4 голосов
/ 13 октября 2008

Часто во встраиваемых системах есть один программист, который пишет весь код, и его / ее характерные черты находятся по всему источнику. Многие программисты встраиваемых систем были инженерами HW и должны были запустить систему как можно лучше. Не было ни требования, ни понятия «мобильность». Еще одно соображение во встраиваемых системах - это то, что компилятор относится к процессору HW. Обратитесь к ISA для этого процессора и проверьте все варианты использования логического значения.

3 голосов
/ 13 октября 2008

Что действительно важно знать об этом вопросе, так это тип «var». Вы говорите «булево», но является ли это булем C ++ / C99, или это (весьма вероятно, что это встроенное приложение C), что-то совершенно другого типа, которое используется в качестве логического?

3 голосов
/ 13 октября 2008

Как уже говорили другие, он устанавливает все биты в 1. И, поскольку это встроенный C, вы можете сохранить это в регистр, где каждый бит важен для чего-то, поэтому вы хотите установить их все в 1. I знаю, что я делал подобное при написании на ассемблере.

2 голосов
/ 15 октября 2008

Кроме того, добавление 1 к 0xff устанавливает его в 0 (при условии, что беззнаковый символ), и проверка могла быть в цикле с шагом, равным разрыву.

1 голос
/ 13 октября 2008

Вот вероятная причина: 0xff - это двоичное дополнение 0. Возможно, в вашей встроенной архитектуре сохранение 0xff в переменной более эффективно, чем, скажем, 1, для которого могут потребоваться дополнительные инструкции или константа, хранящаяся в памяти.

Или, возможно, самый эффективный способ проверить «значение истинности» регистра в вашей архитектуре - это инструкция «установить бит». С 0xff в качестве ИСТИННОГО значения не имеет значения , какой бит проверяется ... они все установлены.

Выше, конечно, просто предположение, не зная, какой тип встроенного процессора вы используете. 8-битный, 16-битный, 32-битный? ПИК, AVR, ARM, x86 ???

(Как уже отмечалось, любое целочисленное значение, отличное от нуля, считается ИСТИНОЙ для целей булевых выражений в Си.)

...