我很感兴趣 因此,是时候放下调查镜了,并且由于我无权访问编译器或编译标志,因此需要发挥创造力。另外,由于此代码没有任何意义,因此对每个假设都提出质疑并不是一个坏主意。
首先,让我们检查的实际类型gets
。我有一个小窍门:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
看起来...正常:
/tmp/613814454/Main.cpp:16:19: warning: 'gets' is deprecated [-Wdeprecated-declarations]
Name<decltype(gets)> n;
^
/usr/include/stdio.h:638:37: note: 'gets' has been explicitly marked deprecated here
extern char *gets (char *__s) __wur __attribute_deprecated__;
^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:254:51: note: expanded from macro '__attribute_deprecated__'
# define __attribute_deprecated__ __attribute__ ((__deprecated__))
^
/tmp/613814454/Main.cpp:16:26: error: implicit instantiation of undefined template 'Name<char *(char *)>'
Name<decltype(gets)> n;
^
/tmp/613814454/Main.cpp:12:25: note: template is declared here
template <class> struct Name;
^
1 warning and 1 error generated.
gets
被标记为已弃用并具有签名char *(char *)
。但是那怎么了FirstFactorial(gets(stdin));
编译?
让我们尝试其他方法:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
这给了我们:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
最后,我们得到了一些东西: decltype(8)
。因此,整个内容gets(stdin)
在文字上被输入(8
)。
事情变得奇怪了。编译器错误继续:
/tmp/596773533/Main.cpp:18:26: error: no matching function for call to 'gets'
cout << FirstFactorial(gets(stdin));
^~~~
/usr/include/stdio.h:638:14: note: candidate function not viable: no known conversion from 'struct _IO_FILE *' to 'char *' for 1st argument
extern char *gets (char *__s) __wur __attribute_deprecated__;
所以现在我们得到了预期的错误 cout << FirstFactorial(gets(stdin));
我检查了一个宏,因为 #undef gets
似乎什么也没做,所以看起来它不是宏。
但
std::integral_constant<int, gets(stdin)> n;
它编译。
但
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
不符合预期的错误 n2
行。
再说一次,几乎所有对main
生产线的修改cout << FirstFactorial(gets(stdin));
吐出预期的错误。
而且 stdin
实际上似乎是空的。
所以我只能得出结论,并推测他们有一个小程序可以解析源并尝试(较差)替换 gets(stdin)
在实际将其输入编译器之前为测试用例的输入值。如果有人有更好的理论或实际上知道他们在做什么,请分享!
这显然是非常糟糕的做法。在研究这个问题时,我发现这里至少有一个问题(示例),因为人们不知道那里有一个站点可以这样做,所以他们的回答是“不要使用gets
use ...代替”,这的确是一个很好的建议,但只会使OP更加混乱,因为任何从stdin进行有效读取的尝试都将在此站点上失败。
TLDR
gets(stdin)
无效的C ++。这个特定网站使用的是一个头(出于什么原因我无法弄清楚)。如果要继续在网站上提交(我既不认可也不不认可),则必须使用此结构,否则该结构将无济于事,但请注意它很脆弱。几乎所有对的修改main
都会吐出一个错误。在此站点之外,请使用常规的输入阅读方法。
stdin
在标准库中为FILE*
,并且任何类型的指针都将转换为char*
,这是的参数类型gets()
。但是,永远不要在混乱的C竞赛之外编写此类代码。如果您的编译器甚至接受它,请添加更多警告标志,并且如果您要修复其中包含该构造的代码库,请将警告变为错误。