60 votes

Que se passe-t-il ici dans ce code C ++?

Quelqu'un peut-il s'il vous plaît expliquer ce qui se passe dans ce code C ++. Il compile et s'exécute correctement sur Linux.

 #include <iostream>
using namespace std;
int main = ( cout << "Hello world!\n", 195 );
 

68voto

Atom Points 8739

Le nombre "195" est le code d'instruction RET sur x86.

Le compilateur C++ (gcc dans mon cas) est incapable de reconnaître que "principal" n'est pas déclaré comme une fonction. Le compilateur ne voit qu'il y a la "main" d'un symbole, et suppose qu'il fait référence à une fonction.

Le code C++

int main = ( cout << "Hello world!\n", 195 );

initialisation d'une variable dans le fichier-portée. Ce code d'initialisation est exécutée avant que le C/C++ environnement demande de main(), mais après il initialise le "cout" de la variable. L'initialisation de l'affiche "Hello, world!\n", et définit la valeur de la variable "principal" à 195. Après l'initialisation est fait, le C/C++ environnement effectue un appel à la "main". Le programme renvoie immédiatement à partir de cet appel parce que nous avons mis une instruction RET (code 195), à l'adresse de "principal".

Exemple GDB de sortie:

$ gdb ./a
(gdb) break _fini
Breakpoint 1 at 0x8048704
(gdb) print main
$1 = 0
(gdb) disass &main
Dump of assembler code for function main:
   0x0804a0b4 <+0>:     add    %al,(%eax)
   0x0804a0b6 <+2>:     add    %al,(%eax)
End of assembler dump.
(gdb) run
Starting program: /home/atom/a 
Hello world!

Breakpoint 1, 0x08048704 in _fini ()
(gdb) print main
$2 = 195
(gdb) disass &main
Dump of assembler code for function main:
   0x0804a0b4 <+0>:     ret    
   0x0804a0b5 <+1>:     add    %al,(%eax)
   0x0804a0b7 <+3>:     add    %al,(%eax)
End of assembler dump.

39voto

Alex B Points 34304

Il n'est pas valide d'un programme C++. En fait, il se bloque pour moi sur Mac OSX après l'impression de "Hello World".

Démontage montre main est une variable statique, et il y a des initialiseurs:

global constructors keyed to main:
0000000100000e20    pushq   %rbp
0000000100000e21    movq    %rsp,%rbp
0000000100000e24    movl    $0x0000ffff,%esi
0000000100000e29    movl    $0x00000001,%edi
0000000100000e2e    leave
0000000100000e2f    jmp __static_initialization_and_destruction_0(int, int)

Pourquoi est-il print "Hello World"?

La raison pour laquelle vous voir "Hello World" imprimé est parce qu'il est exécuté pendant l'initialisation statique d' main, la statique de la variable de type entier. Les initialiseurs statiques sont appelés avant le C++ runtime tente même de l'appel d' main(). Quand il le fait, il se bloque, parce qu' main n'est pas une fonction valide, il est juste un entier 195 dans la section de données de l'exécutable.

D'autres réponses indiquent que c'est valide ret instruction et il fonctionne très bien sous Linux, mais il bloque sur OSX, car la section est marquée comme non-exécutable par défaut.

Pourquoi pas un compilateur C++ dire que main() n'est pas une fonction et arrêter avec l'éditeur de liens d'erreur?

main() a C de liaison, de sorte que le linker ne peut pas dire la différence entre le type de symboles. Dans notre cas, _main réside dans la section de données.

start:
0000000100000eac    pushq   $0x00
0000000100000eae    movq    %rsp,%rbp
...
0000000100000c77    callq   _main ; 1000010b0
0000000100000c7c    movl    %eax,%edi
0000000100000c7e    callq   0x100000e16 ; symbol stub for: _exit
0000000100000c83    hlt
...
; the text section ends at 100000deb

5voto

James Kanze Points 96599

Ce n'est pas un programme légal, mais je pense que la norme est un peu ambiguë quant à savoir si un diagnostic est requis ou s'il s'agit d'un comportement indéfini. (Du point de vue de la qualité de la mise en œuvre, je m'attendrais à un diagnostic.)

1voto

Ed Heal Points 24309

Il affectera à la variable globale main (un entier) la valeur de 195 après avoir imprimé Hello world . Vous aurez toujours besoin de définir la fonction main pour l'exécuter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X