`int main(int argc, char* argv<::>)` 如何成为 main 函数的有效签名?

10

我在某个网站看到过,int main(int argc, char* argv<::>)也可以作为main函数的签名。令人惊讶的是,下面的程序:

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

该代码在GCC和Clang编译器下能够无警告地编译通过。同时,它也可以在C++中进行编译。

那么,为什么int main(int argc, char* argv<::>)main函数的有效签名呢?


11
<::> 是代表 [] 的双字符符号。请参阅http://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C。 - Michael Burr
2个回答

13

char* argv<::>相当于char* argv[]。这里使用的<::>是双字母符号。

C11: 6.4.6(p3):

  

在语言的所有方面中,六个标记79)

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

分别与六个记号的行为相同

[ ] { } # ##

除了拼写之外。80)

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

调用上述宏

stringize( %:);  

将打印

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

字符串化,你是指 # 吗?有什么区别吗? - Radiodef
1
@Radiodef; 是的。第6.10.2节说:否则,参数中每个预处理标记的原始拼写在字符字符串字面值中保留 - haccks
1
不知道这是标准中的一部分! - Spikatrix
3
有地震了,我跑了 :)。现在增加一个例子来演示差别。 - haccks

8
<::>双字符,它们分别相当于[]

我认为它们唯一的现实应用是创建混淆代码,就像您展示的代码一样,但它们是C99标准的一部分,旨在替代自C语言诞生以来一直存在的更加令人尴尬的三字符

最初的目的是帮助使用缺少某些标点符号的国家字符集的程序员。由于现在很少遇到不支持(至少)8位字符集(例如允许像Ä这样的字符与[并存)的环境,因此这个问题基本上无关紧要了。但是向后兼容性仍然被认为是必要的。


4
双字母组合和三字母组合并不是为了支持混淆而设计的,也没有任何功能是出于这个目的存在的。 - David Heffernan
3
@DavidHeffernan说过,他并没有说这些工具旨在支持混淆,只是它们被用于这个目的。它们的初衷是为了支持程序员(尤其是在北欧国家),因为他们的国家字符集中缺少某些标点符号,但这个问题现在已经不再存在。 - rici
2
仍有程序员需要和使用这些功能。例如,北欧国家尚未沉入海中。 - Peter
1
使用双字符和三字符的原因有很多:键盘可能没有覆盖整个语言字符集的按键,输入特殊字符可能很困难,文本编辑器可能会为某些字符保留特殊用途等等。来源:维基百科 - haccks
2
@ChrisD:来自《美国传统科学词典》的定义 - “di-”是一个前缀,表示“两个”,“两倍”或“双倍”。在化学中常用,例如二氧化物,指具有两个氧原子的化合物。因此,digraph是由两个字符组合表示另一个单一字符的组合。同样,在C语言中有三个字符表示另一个字符的trigraphs。 - Michael Burr
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接