2013-08-01 3 views
2

Следующая программа выглядит как макрос C, который вызывает себя.Макрос, который вызывает себя, сам печатает?

#define q(k)int puts();int main(){puts(#k"\nq("#k")");} 
q(#define q(k)int puts();int main(){puts(#k"\nq("#k")");}) 

It compiles and runs fine. Он распечатывается.

Действительно ли этот код C? То есть, полагается ли что-либо за пределами стандартного C работать правильно?

@devnull отметил, что this question имеет аналогичную программу:

#define q(k)main(){return!puts(#k"\nq("#k")");} 
q(#define q(k)main(){return!puts(#k"\nq("#k")");}) 

полагаются ли эта программа на что-либо за пределами стандартного C, чтобы работать правильно?

+1

Кажется, очень похоже на http://stackoverflow.com/questions/8200668/can-you-help-me-with-a-short-code-that-can-print-себя – devnull

+0

@devnull: Я изменил вопрос, чтобы сделать его более отличительным. Тот, на который вы ссылаетесь, на самом деле не соответствует ни одному стандарту С. – jxh

+0

Aha! поэтому вам кажется, что это соответствует стандарту. Тогда почему вы задаете один и тот же вопрос? – devnull

ответ

7

Первая программа представляет собой пример реализации quine в C. На высоком уровне он определяет макрос q(), который создает определение main(), которое выводит две строки. Первая строка является аргументом сама по себе, вторая строка - это аргумент, заключенный в вызов q(). Таким образом, следующая программа:

#define q(k)int puts();int main(){puts(#k"\nq("#k")");} 
q(foo) 

Расширяет в:

int puts();int main(){puts("foo""\nq(""foo"")");} 

После компиляции и запуска, это приводит к выходу:

foo 
q(foo) 

Подставив определение макроса непосредственно на месте foo приводит к quine. Макрос действительно не вызывает себя, он вызывается в том же тексте, который его определяет. В C макросы не расширены рекурсивно (C.99 § 6.10.3.4 ¶ 2).

Как указано в вопросе, программа компилируется без жалобы в GCC с использованием строгих настроек C.99 (-pedantic -std=c99). Программа использует только стандартные функции C и соответствует как C.99, так и C.11.

  • Макро замена (C.99 § 6.10.3), с аргументом substituion (C.99 § 6.10.3.1) и # "stringifying" оператора (C.99 § 6.10.3.2).
  • Объявление функции с неуказанным списком аргументов (C.99 § 6.7.5.3 ¶ 14).
  • Строка литеральной конкатенации (C.99 § 5.1.1.2 ¶ 1).
  • По умолчанию main() возвращаемое значение (C.99 § 5.1.2.2.3 ¶ 1).

Особо следует отметить, что программа не полагается на кодирование символов ASCII.

Программа будет скомпилирована на компиляторе C.89-90, но поведение, не возвращающее значение от main(), не определено для C.89-90. Программа может быть тривиально модифицирована, чтобы стать совместимой с C.89-90, добавив return 0; после вызова puts().

Что касается второй программы, это также вопрос. Однако это не C.89-90, не C.99, ни C.11. Это связано с тем, что он полагается на puts() для возврата положительного числа для оператора логического вывода, так что возвращаемое значение равно 0. Однако для C требуется только puts() вернуть неотрицательное значение при успешном завершении (C.99 § 7.19.7.10 ¶ 3). Только C.89-90 допускает неявные декларации функций (C.89, § 3.3.2.2). Программа может быть изменена в соответствии с C.89-90, удалив return!, а затем добавив return 0; после вызова puts().

Структура этих программ во многом вдохновлена ​​реализацией программы «quine» на «вымышленном» языке BlooP, представленной в книге Gödel, Escher, Bach: An Eternal Golden Braid Дугласом Р. Хофстадтером (зачисленной за то, что она придумала термин «quine»).

DEFINE PROCEDURE "ENIUQ" [TEMPLATE]: PRINT [TEMPLATE, LEFT-BRACKET, 
QUOTE-MARK, TEMPLATE, QUOTE-MARK, RIGHT-BRACKET, PERIOD]. 
ENIUQ 
['DEFINE PROCEDURE "ENIUQ" [TEMPLATE]: PRINT [TEMPLATE, LEFT-BRACKET, 
QUOTE-MARK, TEMPLATE, QUOTE-MARK, RIGHT-BRACKET, PERIOD]. 
ENIUQ']. 

Как и в сторону, вот версия программы, которая печатает исходный код в обратном порядке:

#define q(k)r(char*s){if(*s)r(s+1);putchar(*s);}main(){r(#k"\nq("#k")\n");} 
q(#define q(k)r(char*s){if(*s)r(s+1);putchar(*s);}main(){r(#k"\nq("#k")\n");}) 

 Смежные вопросы

  • Нет связанных вопросов^_^