Я видел следующие макроопределения в книге кодирования.
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Там не было объяснений.
Пожалуйста, объясните мне, как они будут работать как TRUE
и FALSE
.
Я видел следующие макроопределения в книге кодирования.
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Там не было объяснений.
Пожалуйста, объясните мне, как они будут работать как TRUE
и FALSE
.
Посмотрим: '/' / '/'
означает char
литерал /
, деленный на char
литерал '/'
. Результатом является один, который звучит разумно для TRUE
.
И '-' - '-'
означает char
литерал '-'
, вычитаемый из себя. Это значение равно нулю (FALSE
).
Есть две проблемы с этим: во-первых, он не читается. Использование 1
и 0
абсолютно лучше. Кроме того, как указывали TartanLlama и KerrekSB, если вы когда-либо собираетесь использовать это определение, пожалуйста, добавьте круглые скобки вокруг них, чтобы у вас не было сюрпризов:
#include <stdio.h>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
printf ("%d\n", 2 * FALSE);
return 0;
}
Это напечатает значение char
literal '-'
(45 в моей системе).
С круглыми скобками:
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
программа корректно выводит нуль, даже если не имеет смысла умножать значение истины на целое число, но это всего лишь пример неожиданных ошибок, которые могут укусить вас, если вы не в скобках своих макросов.
Это просто еще один способ написания
#define TRUE 1
#define FALSE 0
Выражение '/'/'/'
само по себе разделит значение char '/'
, что даст результат 1.
Выражение '-'-'-'
будет вычитать значение char '-'
от самого себя, что даст в результате 0.
Скобки вокруг всего выражения define
отсутствуют, хотя это может привести к ошибкам в коде с использованием этих макросов. Jay отвечает, это довольно хорошо.
Примером сценария "реальной жизни", в котором забывание скобок может быть вредным, является совместное использование этих макросов с оператором литья в стиле C. Если кто-то решит включить эти выражения в bool
в С++, например:
#include <iostream>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
std::cout << "True: " << (bool) TRUE << std::endl;
std::cout << "False: " << (bool) FALSE << std::endl;
return 0;
}
Здесь мы получаем:
True: 0
False: -44
Итак, (bool) TRUE
будет фактически оценивать до false
, а (bool) FALSE
будет оценивать до true
.
Это эквивалентно записи
#define TRUE 1
#define FALSE 0
То, что на самом деле выполняет выражение '/'/'/'
, делит символ /
(независимо от его числового значения), поэтому он становится 1
.
Аналогично, выражение '-'-'-'
вычитает символ -
из себя и оценивается как 0
.
Лучше написать
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
чтобы избежать случайного изменения значений при использовании с другими операторами с более высоким приоритетом.
Джей уже ответил, почему значения этих выражений 0
и 1
.
Для истории эти выражения '/'/'/'
и '-'-'-'
взяты из одной из записей 1-й Международный конкурс Obfuscated C Code в 1984 году:
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
(Ссылка на программу здесь, есть намек на то, что эта программа делает на странице IOCCC выше.)
Также, если я правильно помню эти выражения как запутанные макросы для TRUE
и FALSE
, также были рассмотрены в "Obfuscated C and Other Mysteries" книга Дона Либеса (1993).
Пусть начнется с true. Вы можете прочитать его как '/' / '/'
, что означает "символ" /', разделенный символом'/'. Поскольку каждый символ в C является числовым значением (по одному байту), его можно читать как "значение ASCII символа" / ", деленное на значение ASCII того же символа", что означает 1 (поскольку, очевидно, x/x равно 1). Следовательно, TRUE
равно 1.
Для FALSE
, его те же рассуждения: '-'-'-'
читает '-' - '-'
, то есть "значение ASCII '-' за вычетом значения ASCII '-'", которое равно 0. Следовательно, FALSE
0.
Это неприятный способ сформулировать очевидное.
Это веселый способ для написания макросов для True
и False
.
Как было сделано много объяснений, /
означает 1-байтовое число (согласно ASCII), когда он делит сам по себе, он дает вам 1
, который будет обрабатываться как True
, а также -
снова является байтовым числом при вычитании того же значения он дает вам 0
, который будет интерпретироваться как False
#define TRUE '/'/'/'
#define FALSE '-'-'-'
следовательно, мы можем заменить /
или -
на любой char, который нам нравится, например:
#define TRUE '!'/'!'
#define FALSE 'o'-'o'
Будет иметь то же значение, что и исходное выражение.