Подтвердить что ты не робот

Странное определение FALSE и TRUE, почему?

В некотором коде, над которым я работаю, я столкнулся с странными переопределениями правды и ложности. Я видел такие вещи раньше, чтобы сделать проверки более строгими/определенными, но это немного странно в моем сознании, и мне интересно, может ли кто-нибудь сказать мне, что может быть хорошей причиной для таких определений, см. Ниже с моими комментариями рядом с ними

#define FALSE (1 != 1) // why not just define it as "false" or "0"?
#define TRUE (!FALSE)  // why not just define it as "true" or "1"?

В этой базе кода есть много других странных странностей. Как и переопределения для всех стандартных типов, таких как:

#define myUInt32 unsigned integer // why not just use uint32_t from stdint?

Все эти маленькие "причуды" заставляют меня чувствовать, что я пропускаю что-то очевидное, но я действительно не вижу смысла: (

Примечание. Строго это код С++, но его можно было портировать из проекта 'c'.

4b9b3361

Ответ 1

Цель представляется переносимостью.

#define FALSE (1 != 1) // why not just define it as "false" or "0"?
#define TRUE (!FALSE)  // why not just define it as "true" or "1"?

Они имеют логический тип на языках, которые его поддерживают (С++), но при этом предоставляют все еще полезные числовые значения для тех, кто этого не делает (С++, даже C99 и C11, по-видимому, несмотря на их получение явных булевых типов данных).

Имея булевы, где это возможно, хорошо подходит для перегрузки функций.

#define myUInt32 unsigned integer // why not just use uint32_t from stdint?

Это прекрасно, если stdint доступно. Вы можете воспринимать такие вещи как должное, но это большой широкий мир! Этот код распознает это.

Отказ от ответственности: Лично я придерживаюсь стандартов и просто заявляю, что компиляторы, выпущенные позднее 1990 года, являются предварительным условием. Но мы не знаем, каковы основные требования к проекту, о котором идет речь.

TRWTF заключается в том, что автор рассматриваемого кода не объяснил это в комментариях рядом.

Ответ 2

#define FALSE (1 != 1) // why not just define it as "false" or "0"?

Я думаю, что это потому, что тип выражения (1!=1) зависит от поддержки языка для логического значения — если это С++, тип bool, иначе это int.

С другой стороны, 0 всегда int, на обоих языках и false не распознается в C.

Ответ 3

Строго это код С++, но его можно было портировать из проекта 'c'.

Речь идет о переносимости, как упоминалось ранее, но она действительно выходит далеко за пределы. Это умный эксплойт определений языка для соответствия языкам.

Эти абсурдные макросы не так абсурдны, как кажется на первый взгляд, но они на самом деле гениальны, поскольку они гарантируют как C, так и С++, что TRUE и FALSE имеют правильные значения (и тип) TRUE и FALSE (даже если компилятор является компилятором C, который не имеет этих ключевых слов, поэтому вы не можете тривиально написать что-то вроде #define TRUE true).

В коде С++ такая конструкция будет бесполезной, поскольку язык определяет TRUE и FALSE как ключевые слова.
Однако, чтобы C и С++ легко взаимодействовали в одной и той же базе кода, вам нужно "что-то", которое работает для обоих (если вы не хотите использовать другой стиль кода).

Способ определения этих макросов является показанием стандарта С++ о явной неопределенности в отношении того, какие значения имеют значения TRUE и FALSE. Стандарт С++ гласит:

Значения типа bool являются либо истинными, либо ложными.
[...]
Значение нуля, значение нулевого указателя или значение указателя нулевого элемента преобразуется в значение false; любое другое значение преобразуется в значение true. [...]
PRvalue типа bool может быть преобразовано в prvalue типа int, при этом false становится равным нулю, а true становится единым.

Обратите внимание, что в нем указано, что существуют два конкретных значения и каковы их имена, и какие соответствующие значения целочисленного значения они преобразуют в и из, но не говорит, что эти значения. Возможно, вы склонны думать, что значения, очевидно, 0 и 1 (и, кстати, вы, возможно, догадались), но это не так. Фактические значения намеренно не определены.

Это аналогично тому, как определяются указатели (и, в частности, нулевой указатель). Помните, что целочисленный литерал нуля преобразуется в нулевой указатель и что nullpointer преобразуется в FALSE, сравнивает равные... blah blah... и т.д. И т.д.
Много говорится о том, что преобразует в то, что и что-то еще, но не говорит, где нулевой указатель должен иметь двоичное представление нуля (и на самом деле существуют некоторые экзотические архитектуры, где это не так!).

Ответ 4

Многие из них имеют исторические причины, такие как старые коды, перенесенные из C, коды из нестандартных компиляторов С++, коды кросс-компиляторов (переносимость), для поддержки обратной совместимости, следующих стилей кода, вредных привычек.

Были некоторые компиляторы, у которых не было <cstdint> для целых типов типа uint32_t, или у них не было <cstdbool>. Хороший программист должен был определить все и использовать предварительные процессоры, чтобы сделать его программу хорошо определенной для разных компиляторов.

Сегодня мы можем использовать <cstdint>, true/false, <cstdbool>,... и все счастливы!

Ответ 5

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

Ответ 6

C не имеет родного булева типа, поэтому вы не можете строго использовать "false" или "true", не определяя их в другом месте, и как бы вы тогда определили это?

Тот же аргумент применим к myUInt32 - C изначально не имел uint32_t и другие типы в stdint, поэтому это обеспечивает возможность получения правильного размера целого числа. Если вы портировали другую архитектуру, вам просто нужно изменить определение myUInt32 на то, что приравнивается к целому числу без знака, равному 32 битам, - будь то длинный или короткий.

Ответ 7

Есть хорошее объяснение, в котором говорится о различии между false и FALSE. Я думаю, что это может помочь в понимании бит, хотя большинство ответов объяснили это. здесь