我们可以省略函数参数的数据类型吗?

4

在学习C语言的quine程序时,我发现主函数只传递了a,没有数据类型。下面的程序可以正常运行并正确输出结果。

main(a){printf(a="main(a){printf(a=%c%s%c,34,a,34);}",34,a,34);}

我想知道,这个程序是如何工作的(不是实际的quine程序),但是a的数据类型是什么?它得到了什么值?


你没有收到警告吗?正如其他人指出的那样,类型默认为 int。顺便说一下,该程序表现出未定义的行为,因为你将一个 char* 赋值给了一个 int - Spikatrix
@CoolGuy - 意图(和错误)是将 a=%c%s%c 放在双引号中 - "a=%c%s%c"。至少那部分没有编译,我非常确定。 - ryyker
3个回答

3
首先,考虑到托管环境,上述代码是非标准的编码方式,而且非常不好。你不应该这样编写代码。
这段代码利用了遗留C的“默认转为int”属性。自 C99 标准以来,此属性已被删除。编译器可能因为历史原因而支持和接受它。
很可能,它曾经获得类似于 argc 的值。

哪个标准?只有一个有效的标准:-) 一旦发布了继任者,所有先前的标准都已被撤回。 - too honest for this site

3

一般函数和main()函数是不同的,main()是一个特殊情况。

对于普通函数而言,在过时版本的C中,你使用的语法会被视为“implicit int”,你的函数将变成int func (int);。这种无意义的特性在16年前就被从该语言中移除了,这样的程序将不再编译。

至于main()的形式,有一些特殊情况,在这个答案中详细描述了所有情况。

该回答的TL;DR:

  • 你代码中的main()形式不允许用于托管C90实现。
  • 其他任何托管C实现也可能不允许(标准含糊)。
  • 这段代码可能适用于某些鲜为人知的脱机实现。但在这种情况下,这段代码没有意义。
  • 或者最有可能的是:这段代码是非标准的,根本无法在任何符合规范的编译器上编译。

1
术语混乱:严格符合的“编译器”并不存在;符合性,无论是严格还是非严格,都是程序的属性。 - Jens
@Jens - 我很好奇你会用什么短语来描述一个包含非标准或非可移植特性的编译器?(例如GCC及其所有非标准扩展)。像“严格符合”或“宽松符合”这样的短语在其意义上似乎很清楚。 - ryyker
1
@Ryyker:由于所有编译器都允许扩展,发明一个与任何编译器匹配的名称实际上是毫无意义的。符合 C 标准所定义的一致性有非常精确的含义。你知道吗,即使编写一个严格符合的 Hello World 程序都很难? "它不应产生依赖于任何未指定、未定义或实现定义行为的输出,并不应超过任何最小实现限制。" 然而,符合实现 的概念是存在的(接受任何严格符合的程序)。 - Jens

1

a的数据类型是什么?

它是一个int。这是旧时代的遗留问题,当时C对象被认为是int,除非明确声明。

它得到了什么值?

这是一个更棘手的问题。试图将格式字符串的地址赋给a。在过去,人们经常将指针分配给int,反之亦然。但是,从来没有规定说sizeof(char*) == sizeof(int),实际上,在我的编译器(clang 7)中,char*是8字节,而int只有4字节。这就是为什么你的程序可以编译(带有六个警告),但在运行时会导致段错误。


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