Dans une interview, j'ai été confronté à une question comme celle-ci:
Votre ami vous a donné un seul fichier de code source qui imprime les numéros de Fibonacci sur la console. Notez que le bloc main () est vide et ne contient aucune instruction.
Expliquez comment cela est possible (indice: instance globale!)
Je veux vraiment savoir à ce sujet, comment une telle chose peut même être possible!
assert
ou#pragma message
etc. Cela redirigera la sortie vers la console pendant la compilation. Le programme peut même ne jamais être entièrement compilé, mais c'est certainement une façon amusante de montrer votre réflexion «hors de la boîte» pendant l'entretien. Cela satisfait la question citée car il ne mentionne rien au sujet du binaire généré; il parle plutôt d'un fichier C qui peut afficher des "trucs" sur la console. ;-)Réponses:
Il est très probablement implémenté comme (ou une variante de celui-ci):
void print_fibs() { //implementation } int ignore = (print_fibs(), 0); int main() {}
Dans ce code, la variable globale
ignore
doit être initialisée avant d'entrer enmain()
fonction. Maintenant, pour initialiser le global,print_fibs()
doit être exécuté là où vous pouvez faire n'importe quoi - dans ce cas, calculer les nombres de fibonacci et les imprimer! Une chose similaire que j'ai montrée dans la question suivante (que j'avais posée il y a longtemps):Notez qu'un tel code n'est pas sûr et doit être évité en général. Par exemple, l'
std::cout
objet peut ne pas être initialisé lorsqu'ilprint_fibs()
est exécuté, si oui, que feraitstd::cout
-il dans la fonction? Cependant, si dans d'autres circonstances, cela ne dépend pas d'un tel ordre d'initialisation, alors il est prudent d'appeler des fonctions d'initialisation (ce qui est une pratique courante en C et C ++).la source
std::ios_base::Init
objet. Et<iostream>
est garanti de se comporter "comme si" il contenait une instance d'unstd::ios_base_Init
objet à la portée de l'espace de noms.(print_fibs(), 0)
estint
. Voici la démo en ligne .bool
, et la variablebool fibsPrinted
. C'est probablement un peu plus propre si la fonction ne sert qu'ici. (Mais la différence n'est probablement pas suffisante pour s'inquiéter.)std::cout
est quelque part dans la bibliothèque. Mais comme je l'ai déjà souligné, la norme exige qu'il soit initialisé avant que le premier constructeur d'unstd::ios_base::Init
objet ne soit terminé, et il exige que notamment<iostream>
se comporte comme si unstd::ios_base::Init
objet était défini à la portée de l'espace de noms. Si l'unité de traduction inclut<iostream>
avant la définition de l'objet en cours d'initialisation, la constructionstd::cout
est garantie.J'espère que cela t'aides
class cls { public: cls() { // Your code for fibonacci series } } objCls; int main() { }
Ainsi, dès qu'une variable globale de la classe est déclarée, le constructeur est appelé et là vous ajoutez la logique pour imprimer la série de Fibonacci.
la source
Oui c'est possible. Vous devez déclarer une instance globale d'un objet qui calcule les nombres de Fibonacci dans le constructeur d'objet.
la source
Je connais quelques exemples comme celui que vous racontez. Une façon de l'obtenir consiste à utiliser la métaprogrammation du modèle. En l'utilisant, vous pouvez déplacer un processus de calcul vers la compilation.
Ici vous pouvez obtenir un exemple avec les nombres de Fibonacci
Si vous l'utilisez dans un constructeur de classe statique et que vous pouvez écrire les nombres sans avoir besoin d'écrire de code dans la fonction principale.
J'espère que cela vous aide.
la source
Des choses peuvent se produire lors de l'initialisation des variables globales / statiques. Le code sera déclenché au démarrage de l'application.
la source
Tous les constructeurs [*] pour les objets de portée fichier sont appelés avant d'atteindre
main
, comme toutes les expressions d'initialisation pour les variables de portée fichier non objet.Edit: De plus, tous les destructeurs [*] pour tous les objets de portée fichier sont appelés dans l'ordre inverse de la construction après les
main
sorties. Vous pourriez, en théorie, mettre votre programme fibonacci dans le destructeur d'un objet.[*] Notez que «tous» ignore le comportement de chargement et de déchargement dynamique des bibliothèques avec lesquelles votre programme n'était pas directement lié. Cependant, techniquement, ceux-ci sont en dehors du langage C ++ de base.
la source
main
?main
est vide, donc ces DLL / DSO devraient être chargées par des destructeurs, ce qui est sacrément pervers. Mais, étant de l'informatique, je suppose que nous devrions être prudents avec des mots comme «tous».