begin process at 2010 02 09 18:46:26
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Astuces

 > CONNAISSEZ VOUS PRINTF ?

CONNAISSEZ VOUS PRINTF ?


 Information sur la source

Note :
9 / 10 - par 1 personne
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Astuces Niveau :Débutant Date de création :20/02/2004 Vu :6 353

Auteur : vieuxLion

Ecrire un message privé
Commentaire sur cette source (6)
Ajouter un commentaire et/ou une note

 Description

printf est la première fonction que nous utilisons dans le fameux programme "Hello World" du débutant.
Son fonctionnement est simple, on lui donne une chaîne de format dans laquelle sont placés des codes %d, %s... ET on lui fournit les arguments correspondants...
Et si on les oublie ! Que se passe t-il ?



Source

  • Prenons le code suivant :
  • int main(int argc, char* argv[])
  • {
  • printf("nombre d'arguments = %d\n", argc);// %d attend un entier ... on lui donne
  • return 0;
  • }
  • le résultat est évident .
  • De même pour celui ci :
  • int main(int argc, char* argv[])
  • {
  • printf("nom du programme = %s\n", argv[0]);// %s attend une chaine ... on lui donne
  • return 0;
  • }
  • Et le suivant :
  • int main(int argc, char* argv[])
  • {
  • printf("adresse du 1er argument = %p\n", argv[0]);// %p attend un pointeur... on lui donne
  • return 0;
  • }
  • mais que pensez vous de celui là ?
  • int main(int argc, char* argv[])
  • {
  • printf("pile:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");// ... on ne lui donne rien
  • return 0;
  • }
  • nous avons "oublié" les arguments
  • Que fait la fonction printf à votre avis ?
  • Elle plante ?
  • Pas du tout, elle nous renvoie le contenu de la PILE
  • Lorsque nous passons des arguments à une fonction, le compilateur génère le code nécessaire (on appelle cela le prologue) pour empiler ces arguments sur ... la pile.
  • Lorsque l'on demande à printf d'écrire un entier, nous lui passons généralement l'entier. Celui ci est empilé et la fonction n'a qu'a le dépiler.
  • Elle travaille donc normalement lorsque nous oublions de lui passer les arguments et elle nous fournit le contenu de sa pile.
  • Bien sûr, il y a plus simple pour voir la pile : l'utilisation d'un débogueur.
  • Pour s'en convaincre, utiliser la fenêtre "memory" sous Visual Studio
  • Remarque : attention aux options de compilations
  • Il est bon de désactiver les options d'optimisation pour "comprendre la pile"
  • Les conventions d'appel sont importantes aussi : par défaut __cdecl (/Gd)
  • Autre moyen :
  • utiliser l'adresse ESP et un peu d'assembleur __asm { mov p, esp}
  • ainsi :
  • int main(int argc, char* argv[])
  • {
  • int * p =0;
  • __asm { mov p, esp}
  • printf("adresse de pile = %p\n", p);
  • printf("contenu de pile :\nAdresse\t\tContenu\n");
  • int * pFin = p-5;
  • for (;p>pFin; p--)
  • printf("%p\t%08X\n", p, *p);
  • return 0;
  • }
Prenons le code suivant :
int main(int argc, char* argv[])
{
 printf("nombre d'arguments = %d\n", argc);// %d attend un entier ... on lui donne
 return 0;
}

le résultat est évident .

De même pour celui ci :
int main(int argc, char* argv[])
{
printf("nom du programme = %s\n", argv[0]);// %s attend une chaine ... on lui donne
return 0;
}

Et le suivant :
int main(int argc, char* argv[])
{
printf("adresse du 1er argument = %p\n", argv[0]);// %p attend un pointeur... on lui donne
return 0;
}

mais que pensez vous de celui là ?
int main(int argc, char* argv[])
{
printf("pile:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");//  ... on ne lui donne rien
return 0;
}

nous avons "oublié" les arguments
Que fait la fonction printf à votre avis ?
Elle plante ? 
Pas du tout, elle nous renvoie le contenu de la PILE

Lorsque nous passons des arguments à une fonction, le compilateur génère le code nécessaire (on appelle cela le prologue) pour empiler ces arguments sur ... la pile.
Lorsque l'on demande à printf d'écrire un entier, nous lui passons généralement l'entier. Celui ci est empilé et la fonction n'a qu'a le dépiler.
Elle travaille donc normalement lorsque nous oublions de lui passer les arguments et elle nous fournit le contenu de sa pile.

Bien sûr, il y a plus simple pour voir la pile : l'utilisation d'un débogueur.
Pour s'en convaincre, utiliser la fenêtre "memory" sous Visual Studio
Remarque : attention aux options de compilations
Il est bon de désactiver les options d'optimisation pour "comprendre la pile"
Les conventions d'appel sont importantes aussi : par défaut __cdecl (/Gd)

Autre moyen : 
utiliser l'adresse ESP et un peu d'assembleur	__asm { mov p, esp}
ainsi :

int main(int argc, char* argv[])
{
	int * p =0;
	__asm { mov p, esp}
     printf("adresse de pile = %p\n", p);
	printf("contenu de pile :\nAdresse\t\tContenu\n");
	int * pFin = p-5;
	for (;p>pFin; p--)
		printf("%p\t%08X\n", p, *p);
	return 0;
}



 Sources du même auteur

Source avec Zip Source avec une capture UN BUFFEROVERRUN : LE DÉBORDEMENT DE PILE
Source avec Zip Source avec une capture Source .NET (Dotnet) C++ MANAGÉ PAR LES HELLO WORLDS (DOTNET)
Source avec Zip SIMPLE MOYEN DE FAIRE UNE DLL À PARTIR DE FONCTIONS CPP
LE VECTEUR EST UN SACRÉ COPIEUR
Source avec une capture CLASSE CANONIQUE : NI FUITE MÉMOIRE, NI TRAP

 Sources de la même categorie

SMART POINTEUR À COMPTEUR DE RÉFÉRENCE par nirgal76
POINTEUR INTELLIGENT par snpier wolf
ALIGNER TEXTE CONSOLE par CptPingu
QWERTY - AZERTY AVEC SDL, UNE ALTERNATIVE par Scheb
Source avec Zip Source avec une capture INSERER UNE ANIMATION FLASH (WIN32-DEVCPP) par gagah1

Commentaires et avis

Commentaire de JCDjcd le 20/02/2004 20:53:59

Tres interressant comme probleme puisqu'il oblige a se poser la question de comment c'est fait le passage en argument a une fonction en C.
Mais ce probleme est plus visible quand on fait de l'assembleur, car en C le printf sans argument se voit tout de suite ! Les valeures prises par le int et double sont bien connus quand il y a n'importe quoi.
En assembleur c'est plus problematique car le retour a la fonction appellante peut etre decaler si l'on n'a pas fait autant de PUSH que de POP.

Commentaire de Kirua le 21/02/2004 11:27:54

Salut VieuxLion. J'utilise Dev-C++ 4.9.8.0 et quand j'ai copié ton code de fin (avec le tout petit bout d'asm), j'ai pas pu compiler. Est-ce que je dois faire qq ch de spécial pour permettre les instructions assembleur? (pourtant asm est un mot clef "officiel")

l'erreur est une "parse error" au nieau de la parenthèse ouvrante du bloc asm. (j'ai essayé avec __asm et avec asm tout court, même erreur)

Cette erreur est suivie de plein d'autres forcément, mais rien d'utile.

Ça dit qq ch à qq un ? merci d'avance

Commentaire de krust le 21/02/2004 12:53:49

j'ai jamais réussi à faire marcher du code ASM sous dev c++ 4.9.8.0, maintenant j'utilise Visual C++ 6 qui est de loin le meilleur compilateur/Dev Tool Win32 (celon moi).

Donc désolé de pouvoir t'aider, mais je voualis juste que tu sache que tu n'es pas le seul chez qui ça marche pas :)

ciao ;)

Commentaire de Kirua le 21/02/2004 17:46:23

lu krust, j'ai une sainte horreur de VC++, voilà, comme ça c dit ;-)
il doit bien y avoir une soluce pr compiler de l'asm avec GCC non ?

Commentaire de vieuxLion le 21/02/2004 18:06:18

désolé pour ce bout d'asm avec une syntaxe VC++
Il est OK sur VC++6 et 7
Je ne suis pas très bien placé pour GCC mais peut-être ici qq infos :
http://www.osdever.net/tutorials/gccasmtut.php?the_id=68

Commentaire de Calak le 15/09/2004 14:45:13

J'ai souvenir que l'on doit entourer son code ASM avec des quillemets " "

Normalement c ça ^^


Au fait, très bon truc le coup du printf, je m'étais fais la même réflection ce matin :D

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,593 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales