В старых днях (pre-ANSI) предопределение символов, таких как unix
и vax
, было способом разрешить коду во время компиляции определять, в какой системе он компилировался. Официального языкового стандарта тогда не было (помимо справочного материала в конце первого издания K & amp; R), а код C любой сложности, как правило, представляет собой сложный лабиринт #ifdef
s, чтобы допускать различия между системами. Эти макроопределения обычно устанавливались самим компилятором, а не определялись в файле заголовка библиотеки. Поскольку реальных правил о том, какие идентификаторы не могут быть использованы в реализации и которые зарезервированы для программистов, авторы компиляторов могли свободно использовать простые имена, такие как unix
, и предположили, что программисты просто избегают использовать эти имена в своих собственных целях.
В стандарте ANSI C 1989 года введены правила, ограничивающие символы, которые могут быть реализованы на законных основаниях. Макрос, предопределенный компилятором, может иметь только имя, начинающееся с двух символов подчеркивания, или с подчеркиванием, за которым следует заглавная буква, оставляя программистов свободными использовать идентификаторы, не соответствующие этому шаблону и не используемые в стандартной библиотеке.
В результате любой компилятор, который предопределяет unix
или linux
, не соответствует требованиям, поскольку он не сможет скомпилировать совершенно законный код, который использует что-то вроде int linux = 5;
.
Как это происходит, gcc по умолчанию не соответствует требованиям, но может быть сделано для надлежащего соответствия с правильными параметрами командной строки:
gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic
См. руководство gcc для более подробности.
gcc будет постепенно отказываться от этих определений в будущих выпусках, поэтому вам не следует писать код, который зависит от них. Если ваша программа должна знать, компилируется ли она для цели Linux или нет, она может проверить, определен ли __linux__
(если вы используете gcc или компилятор, совместимый с ним). Дополнительную информацию см. В руководстве по препроцессору GNU C .
В значительной степени не имеет значения: победитель «Лучший один лайнер» в 1987 году Международный конкурс по обфускации кода C ], Дэвид Корн (да, автор Korn Shell) воспользовался предопределенным макросом unix
:
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Он печатает "unix"
, но по причинам, которые абсолютно ничего не делают с написанием имени макроса.
Вы можете использовать cross join
, что в MS Access делается с запятой:
select t1.*, t2.ReportDate,
DateDiff("d", t2.ReportDate, t1.Date)
from table1 as t1,
table2 as t2