Является ли это допустимым определением для main()

Стандарт C11 заявляет, что:

5.1.2.2.1 Запуск программы

  1. Функция, вызываемая при запуске программы, называется main. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возвращаемого значения int и без параметров:

    int main(void) { /* ... */ }
    

    или с двумя параметрами (обозначаемыми здесь как argc и argv, хотя могут использоваться любые имена, поскольку они являются локальными для функции, в которой они объявлены):

    int main(int argc, char *argv[]) { /* ... */ }
    

    или эквивалент; 10) или каким-либо другим способом, определяемым реализацией.


10) Таким образом, int можно заменить именем typedef, определенным как int, или тип argv можно записать как char ** argv, и так далее.

Мы проигнорируем эту часть: или каким-либо другим образом, определяемым реализацией, поскольку меня интересуют только определения, эквивалентные двум приведенным выше примерам.

Будет ли это допустимым определением для main, поскольку char* a[4] и char** эквивалентны:

int main(int argc, char* argv[4]){/*...*/}

Как насчет массива VLA, мы предполагаем, что printf вернет положительное значение int:

int main(int argc, char* argv[printf("Hello there!")]){/*...*/}

person this    schedule 23.06.2015    source источник
comment
Обратите внимание, что вы цитируете раздел для размещенных реализаций. В этом разделе не рассматриваются автономные реализации.   -  person Lundin    schedule 23.06.2015
comment
Думаю, было бы интересно спросить, эквивалентны ли им argv[static 4].   -  person Grzegorz Szpetkowski    schedule 23.06.2015
comment
@GrzegorzSzpetkowski: Да, поскольку static не влияет на тип. Конечно, квалификаторы типа, такие как const и restrict, которые также могут использоваться таким образом, влияют на это.   -  person cremno    schedule 23.06.2015


Ответы (2)


Да, это все покрывается "или эквивалентом". Сноска о переименовании параметров или использовании типов typedefed является лишь примером.

Мой любимый вариант

int main(int argc, char* argv[argc+1]){/*...*/}

потому что он содержит больше всего информации о семантике всех main функций.

person Jens Gustedt    schedule 23.06.2015

int main(int argc, char* argv[4]){/*...*/}  

является действительной подписью main. Компилятор будет игнорировать 4 в char argv[4], что эквивалентно char argv[] = char **argv. То же самое и со второй подписью.

person haccks    schedule 23.06.2015
comment
Учитывая, что в C11 выполнение typedef int FOO[printf("Wow");]; приведет к выполнению printf, даже если никакие переменные не объявлены как тип FOO, есть ли в стандарте что-либо, указывающее, что размер аргумента массива не будет оцениваться, а не оцениваться, а результат игнорируется ? - person supercat; 23.06.2015
comment
@суперкот; Ничего против не нашел. - person haccks; 23.06.2015
comment
Вы имеете в виду, что Стандарт, казалось бы, разрешает такое исполнение, но не указывает, что оно происходит? Говорит ли это что-нибудь о законности void foo(int x[-1]) или звонка void foo(int length; int dat[length]), когда length <= 0? Как насчет эффекта void foo(int dat[x++][y++]), когда x и y являются глобальными переменными? - person supercat; 23.06.2015
comment
Говорится ли что-нибудь о допустимости void foo(int x[-1]): Да. Вы получите ошибку компиляции для этого. На самом деле происходит то, что во время компиляции компилятор проверяет, есть ли после [ число/значение +ve или нет. Если есть число +ve (или значение выражения) или ничего нет, тогда все в порядке, иначе возникнет ошибка. void foo(int length; int dat[length]) и void foo(int dat[x++][y++]) вполне допустимы в C99 и более поздних версиях. Прочтите C11: раздел 6.7.6.2 p4 и пример 10. - person haccks; 23.06.2015
comment
Согласно моему прочтению Стандарта, определение функции как void foo(int dat[x++][y++]) {...} потребует, чтобы, если y больше нуля до вызова foo, компилятор должен увеличить его (если y не больше нуля, вызов является UB), но компилятор не должен увеличивать x и не предъявлять никаких требований к его значению? Согласуется ли это с вашим чтением? - person supercat; 23.06.2015
comment
@суперкот; Я думал, что x и y имеют какое-то значение, отличное от 0. Если x и y являются глобальными, то стандарт C не позволит его компилировать, но есть расширение GCC, которое разрешает массив нулевой длины. - person haccks; 23.06.2015
comment
Если y больше нуля во время вызова, зачем требуется какое-либо расширение массива нулевой длины? Мое прочтение таково: при заданном int arr[720]; int x; int y=1; в глобальной области видимости первый вызов foo(arr); будет рассматривать arr как указатель на блок памяти, содержащий 720 одноэлементных массивов, второй — как указатель на блок, содержащий 360 двухэлементных массивов, в качестве указателя на блок, содержащий 240 трехэлементных массивов, затем 180 четырехэлементных массивов, 144 пятиэлементных массива и 120 шестиэлементных массивов. - person supercat; 23.06.2015