Как напечатать от 1 до N без точки с запятой? Объясните этот код
// A recursive C program to print all numbers from 1
// to N without semicoolon
#include<stdio.h>
#define N 10
int main(int num)
{
if (num <= N && printf("%d ", num) && main(num + 1))
{
}
}
Как работает эта программа? Пожалуйста, объясните это
2 ответа
Код в этом ужасном примере опирается на некоторые хрупкие предположения:
main
вызывается с двумя аргументами: int
представляющий количество аргументов, включая имя программы и массив char*
содержащий строку аргумента, оканчивающуюся на NULL
,
В примере предполагается, что определение main()
с одним int
Аргумент создаст код, совместимый с этим соглашением о вызовах, который может быть или не быть действительным и явно описан как имеющий неопределенное поведение в Стандарте C (J.2).
Если он действителен или работает случайно, int
аргумент, полученный main
будет 1
если программа вызывается из командной строки без аргументов.
main()
проверяет, является ли этот аргумент <= N
, другими словами, если значение должно быть напечатано. Если это так, это вызывает printf("%d ", num)
, который выводит десятичное представление num
в stdout
и возвращает количество произведенных символов, 2 для первого числа, которое не равно нулю, поэтому код продолжается и вызывает main
рекурсивно, передавая ему следующий более высокий номер.
Идет, пока все числа до N
были напечатаны, и первый тест в последнем рекурсивном вызове не прошел.
main
затем возвращается 0
(если компилятор соответствует C99 или более позднему стандарту). Каждый рекурсивный вызов возвращается 0
пока первоначальный вызов не вернется 0
в систему.
Код хрупок, потому что main
вызывается нестандартным способом. Было бы немного менее уродливо написать:
#include <stdio.h>
#define N 10
int main(int argc, char *argv[]) {
if (num <= N && printf("%d ", num) && main(num + 1, argv)) {}
}
Обратите внимание, однако, что вызов main()
рекурсивно, как правило, считается плохой практикой.
Пока функция внутри возвращает значение, конвертируемое в bool, оно также будет принято вызываться.
В случае успеха возвращается общее количество написанных символов. При неудаче возвращается отрицательное число.
Выше возвращаемое значение функции printf(). Так что да printf("%d ", num)
в этом случае всегда будет возвращать true и печатать на каждой итерации.