Estoy intrigado. Entonces, es hora de poner las gafas de investigación y, dado que no tengo acceso al compilador o las banderas de compilación, necesito ser inventivo. Además, porque nada de este código tiene sentido, no es una mala idea cuestionar cada supuesto.
Primero, verifiquemos el tipo real de gets
. Tengo un pequeño truco para eso:
template <class> struct Name;
int main() {
Name<decltype(gets)> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Y eso se ve ... normal:
/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
está marcado como obsoleto y tiene la firma char *(char *)
. Pero entonces, ¿cómo está FirstFactorial(gets(stdin));
compilando?
Probemos algo más:
int main() {
Name<decltype(gets(stdin))> n;
// keep this function call here
cout << FirstFactorial(gets(stdin));
return 0;
}
Lo que nos da:
/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
Name<decltype(8)> n;
^
Finalmente estamos consiguiendo algo: decltype(8)
. Por lo tanto, todo gets(stdin)
se reemplazó textualmente con la entrada ( 8
).
Y las cosas se ponen más raras. El error del compilador continúa:
/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__;
Entonces ahora tenemos el error esperado para cout << FirstFactorial(gets(stdin));
Revisé una macro y, como #undef gets
parece no hacer nada, parece que no es una macro.
Pero
std::integral_constant<int, gets(stdin)> n;
Se compila.
Pero
std::integral_constant<int, gets(stdin)> n; // OK
std::integral_constant<int, gets(stdin)> n2; // ERROR wtf??
No con el error esperado en la n2
línea.
Y nuevamente, casi cualquier modificación main
hace que la línea cout << FirstFactorial(gets(stdin));
escupe el error esperado.
Además, la stdin
realidad parece estar vacía.
Por lo tanto, solo puedo concluir y especular que tienen un pequeño programa que analiza la fuente e intenta (mal) reemplazarlo gets(stdin)
con el valor de entrada del caso de prueba antes de realmente introducirlo en el compilador. Si alguien tiene una teoría mejor o realmente sabe lo que está haciendo, ¡comparta!
Obviamente, esta es una muy mala práctica. Mientras investigaba esto, descubrí que hay al menos una pregunta aquí ( ejemplo ) sobre esto y porque la gente no tiene idea de que hay un sitio que hace esto, su respuesta es "no use gets
usar ... en cambio", que es es un buen consejo, pero solo confunde más al OP ya que cualquier intento de una lectura válida de stdin fallará en este sitio.
TLDR
gets(stdin)
es inválido C ++. Es un truco que utiliza este sitio en particular (por qué razones no puedo entender). Si desea continuar enviando en el sitio (no lo estoy respaldando ni lo estoy respaldando), debe usar esta construcción que de otra manera no tendría sentido, pero tenga en cuenta que es frágil. Casi cualquier modificación a main
escupirá un error. Fuera de este sitio, utilice métodos de lectura de entrada normales.
stdin
en cuenta que en la biblioteca estándar hay unFILE*
, y un puntero a cualquier tipo se conviertechar*
, que es el tipo de argumento degets()
. Sin embargo, nunca debes escribir ese tipo de código fuera de un concurso de C ofuscado. Si su compilador incluso lo acepta, agregue más indicadores de advertencia, y si está tratando de arreglar una base de código que tiene esa construcción, convierta las advertencias en errores.