«Int main (vooid)»? Как это работает?

135

Недавно мне пришлось набрать небольшую тестовую программу на Си, и в процессе я допустил орфографическую ошибку в основной функции, случайно использовав vooidвместо void.

И все же это все еще работало.

Сокращая его до самой маленькой полной версии, я получил:

int main (vooid) {
    return 42;
}

Это действительно compile ( gcc -Wall -o myprog myprog.c) и при запуске возвращает 42.

Как именно этот действительный код?


Вот отрывок из моей bashскорлупы, чтобы показать, что я делаю:

pax$ cat qq.c
int main (vooid) {
    return 42;
}

pax$ rm qq ; gcc -Wall -o qq qq.c ; ./qq

pax$ echo $?
42
paxdiablo
источник
Определяя main с помощью одного intпараметра, вы вызываете Undefined Behavior . Все может случиться :)
pmg
9
На самом деле, я не уверен насчет UB, @pmg. ИСО, в частности, допускает другие возможности mainиз стандартных двух канонических. Для переносимости, вы должны использовать один из этих двух, но я не думаю, что UB применяется здесь.
paxdiablo
Хм: в размещенной среде mainдолжна быть одна из 2 канонических форм (2.1.2.2). Но вы правы @pax, в автономной среде идентификатор mainни в коем случае не является особенным: если он используется как функция, он может быть любого типа и иметь любое количество параметров любого типа.
pmg
2
В C99 автономный полностью определяется реализацией. Для хоста раздел 5.1.2.2.1 в конце указывает «или каким-либо другим способом, определяемым реализацией», поэтому он требует, как минимум, две канонические формы, но также может иметь и другие (это позволит UNIXy int main (int argc, char *argv[], char *envp[]);соответствовать ).
paxdiablo

Ответы:

220

Он просто использует синтаксис объявления функции в "старом стиле"; вы неявно объявляете intпараметр с именем vooid.

Оливер Чарльзуорт
источник
2
Кажется, это так. Если вы добавите "vooid = 42; верните vooid;" к основному, вы также получите возвращаемое значение 42.
Джефф Эймс
43
Ааааа, ты прав. Если я добавлю -std=c99, я получу qq.c:1: warning: type of 'vooid' defaults to 'int'.
paxdiablo
70

Это правильный код, потому что myprog.c содержит:

int main (vooid) // vooid is of type int, allowed, and an alias for argc
{     
  return 42; // The answer to the Ultimate Question
} 

vooidсодержит один плюс количество переданных аргументов (т. е. argc). Таким образом, в действительности все , что вы сделали, чтобы переименовать argcв vooid.

Михаил Гольдштейн
источник
11
Если вы делаете "вернуть vooid"; вместо этого он действительно дает 1 + num. арг.
Джефф Эймс
6
@Джефф, название программы считается аргументом, поэтому + 1
Мартин Беккет
23

В С типом по умолчанию для аргумента функции является int. Итак, ваша программа обрабатывает слово vooidкак int main(int vooid), что является совершенно правильным кодом.

Чинмай Канчи
источник
20

Это только gcc -std=c89 -Wall -o qq qq.cи gcc -std=gnu89 -Wall -o qq qq.cне издают предупреждение. Все остальные стандарты выдают предупреждение о неявном типе intfor vooid.

int main(chart)ведет себя так же, как и int main (vooid).

return vooid; возвращает количество аргументов командной строки.

Я тестировал с gcc 4.4.5 в системе тестирования Debian.

vpit3833
источник