Как `int main (int argc, char * argv <::>)` действительная подпись main?

Я видел на сайте, что int main(int argc, char* argv<::>) также может использоваться как подпись main. Удивительно, Следующая программа:

int main(int argc, char* argv<::>)
{
  return 0;
}

компилирует все предупреждения в GCC, а также clang. Он также компилируется в С++.

Итак, как получилось, что int main(int argc, char* argv<::>) является допустимой сигнатурой main?

Ответ 1

char* argv<::> эквивалентен char* argv[]. <: и :>, используемые здесь, являются орграфами.

C11: 6.4.6 (p3):

Во всех аспектах языка шесть токенов 79)

<: :> <% %> %: %:%:

ведут себя соответственно так же, как шесть токенов

[ ] { } # ##

за исключением их правописания. 80)


Примечание для нот:
79). Эти жетоны иногда называют "орграфами".
80) Таким образом, [ и <: ведут себя по-разному, когда "строятся" (см. 6.10.3.2), но в противном случае могут свободно меняться.

Пример:

%: define  stringize(a) printf("Digraph \"%s\" retains its spelling in case of stringization.\n", %:a)    

Вызов макроса

stringize( %:);  

напечатает

Digraph "%:" retains its spelling in case of stringization.

Ответ 2

<: и :> являются орграфами; они эквивалентны соответственно [ и ].

Я считаю, что их единственное использование в реальной жизни - это создание запутанного кода, такого как тот, который вы представляете, но они являются частью стандарта C99, предназначенного для замены еще более неуклюжих триграфов, которые были на C почти навсегда.

Первоначальное намерение состояло в том, чтобы помочь программистам, работающим с национальными наборами символов, которым не хватало определенных знаков препинания. Поскольку в настоящее время довольно редко встречается среда, которая не поддерживает (по крайней мере) восьмибитные наборы символов, позволяя таким символам, как Ä, сосуществовать с [, проблема в основном спорная. Но обратная совместимость по-прежнему считается необходимой.