Стандарт C требует, чтобы реализация поддерживала только две подписи, указанные в вопросе,
1: int main(int argc, const char *argv[]);
2: int main(void);
Для соглашений о вызовах, когда вызывающий объект извлекает аргументы из стека вызовов, последовательность вызова для (1)прекрасно работает для (2) - вызывающая сторона помещает аргументы в стек, вызываемая сторона (main
) никогда не использует их, а вызывающая сторона удаляет их из стека.
Для соглашений о вызовах, когда вызываемый объект появляетсяаргументы из вызывающего стека main
должны были бы быть скомпилированы по-разному в зависимости от того, какая подпись используется.Это было бы проблемой в реализациях с фиксированным фрагментом кода запуска во время выполнения C, поскольку он не знает, как было объявлено main
.Самый простой способ справиться с этим - всегда использовать соглашение о вызовах «вызывающих вызовов» для main
, и именно так работает компилятор Microsoft C - см., Например, https://docs.microsoft.com/en-us/cpp/build/reference/gd-gr-gv-gz-calling-convention,, в котором говорится, что другие вызовыусловные обозначения игнорируются, когда применяются к main
.
PS
_Generic и tgmath.h не оказали никакого влияния на это.
В K & R C не было подписей, только имена аргументов и необязательные объявления типов для них, поэтому для main
.
было только одно возможное соглашение о вызовах.Таким образом, ни одно из этих языковых изменений за десятилетия никак не повлияло на то, как называется main
.