IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Ordre de traitement des parametres dans une fonction


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Ordre de traitement des parametres dans une fonction
    Bonjour à tous ,
    je suis en train d'apprendre le C et je me livre donc à quelques experiences sur de petits bouts de code afin de mieux cerner les mecanismes de ce langage.
    Hier , apres une introduction aux fonctions , j'ai modifié le code d'exemple pour obtenir une sortie supplementaire et observer le traitement des parametres par la fonction.
    Le resultat me montre que la fonction passe les parametres dans l'ordre inverse des appels , comment celà s'explique-t-il ?

    Merci d'avance pour vos reponses.

    Voiçi mon code , je compile via gcc sur Mac OS X , proc@Intel.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include <stdio.h>
     
    int puiss(int base, int n ); // prototype de la fonction -puiss- 
     
    main()
    {
    	int i;
     
    	for ( i = 0 ; i <10 ; ++i )
            // appels à la fonction -puiss-
    		printf("2 à la puissance %d donne : %d  et -3 à la puissance %d donne : %d\n\n", i , puiss(2,i),i ,puiss(-3,i));
     
    	return 0;
    }
     
    int puiss(int base, int n) // FONCTION    eleve base à la puissance n ; n >= 0 
                               // type-de-retour ( int ) nom-de-fontion (puiss ) et ( parametres eventuels )
    {
    	int i,p;
     
    	p=1;
    	for ( i=1 ; i <= n ; ++i)
    	    p = p * base; // p
            // ajout d'une sortie pour visualiser le sens du traitement : sur ma machine , à l'inverse des appels ( -3 puis 2 )	
    	    printf("in fonction: %d à la puissance %d\n",base , n);
     
    		return p ; // retour du resultat de la fonction vers l'appel
    }

  2. #2
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    La norme du langage C ne spécifie pas l'ordre d'évaluation des paramètres effectifs d'une fonction. Cet ordre dépend de la "convention d'appel" utilisée par ton logiciel. La plupart du temps, les compilateurs C génèrent du code avec une convention d'appel qui fait que les paramètres sont évalués de la droite vers la gauche, c'est ce qu'on appelle d'ailleurs la "convention d'appel C". Quelques notions d'assembleur sont utiles pour bien comprendre la nécessité d'une convention d'appel dans un logiciel, bien que ton intuition te le permettrait aussi. A+.

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Merci pour ta reponse , je pensais bien à une convention mais je n'en trouvait pas de trace. Je cherchais donc à le verifier car dans une "machinerie" logicielle, si un bit d'arret se fait griller la priorité quelque chose va clocher ^^

    La partie ASM exige surement une pile, du coup je dois etre dans une logique LIFO non ?

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 371
    Points : 23 626
    Points
    23 626
    Par défaut
    Citation Envoyé par lowbin Voir le message
    La partie ASM exige surement une pile, du coup je dois etre dans une logique LIFO non ?
    Si ! :-)

    Cela dit, certains compilateurs peuvent être paramétrés pour utiliser le maximum de paramètres à travers des registres. Dès lors, la notion d'empilement devient moins marquée, même s'il y a des chances pour que tous les paramètres continuent d'être évalués de cette façon…

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    merci !
    comme je viens de la logique " cablée " , j'attache beaucoup d'importance aux sens des traitements , meme si " court-circuiter " un logiciel de cette façon parait improbable , la sortie logique d'une fonction ne devant s'effectuer qu'à la fin de son execution.
    Si je comprends bien , cette notion pose surtout probleme dans les conversions de type ?

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par lowbin Voir le message
    merci !
    comme je viens de la logique " cablée " , j'attache beaucoup d'importance aux sens des traitements , meme si " court-circuiter " un logiciel de cette façon parait improbable , la sortie logique d'une fonction ne devant s'effectuer qu'à la fin de son execution.
    Si je comprends bien , cette notion pose surtout probleme dans les conversions de type ?
    "Court-circuiter" un logiciel de cette manière n'est pas improbable. En fait, il suffit de s'assurer que l'évaluation de la valeur d'un paramètre dépends de l'évaluation de la valeur d'un autre paramètre et hop, le tour est joué. Un exemple classique :

    f(++i, ++i);

    On entre dans le royaume sans lumière des comportements que la norme spécifie comme étant indéfinis (donc impossible de prévoir ce qui va se passer ; dans notre cas, si a et b sont les paramètres de la fonction, quel est le signe de (a - b)).

    Bien évidemment, il faut éviter de jouer avec ce type de comportements - trop dangereux, et généralement illisibles et incompréhensible pour le développeur qui relit le code. De cette manière, on obtient un comportement normal, aisé à prédire, et qui ne posera pas de problème. De manière général, on fait en sorte que l'ordre d'évaluation des expressions d'un statement (une ligne qui se termine par ';' pour faire simple) n'ai pas d'importance ; car dans ce cas, c'est l'ordre d'évaluation des statements qui a la précédence, et comme lui est aisément identifiable, le code devient lisible.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 371
    Points : 23 626
    Points
    23 626
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    "Court-circuiter" un logiciel de cette manière n'est pas improbable. En fait, il suffit de s'assurer que l'évaluation de la valeur d'un paramètre dépends de l'évaluation de la valeur d'un autre paramètre et hop, le tour est joué. Un exemple classique :

    f(++i, ++i);

    On entre dans le royaume sans lumière des comportements que la norme spécifie comme étant indéfinis (donc impossible de prévoir ce qui va se passer ; dans notre cas, si a et b sont les paramètres de la fonction, quel est le signe de (a - b)).
    En C, c'est même encore plus ambigü car le moment exact où « i » sera effectivement incrémentée n'est pas clairement défini, comme on en parlait dans cette discussion

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Je viens de tester le code de JeitEmgie situé à la fin de votre discussion et je suis effectivement surpris ^^ , pourtant avec des suites d'appels similaires -(i++,i++,i++,i++)- et inversement - les sorties sont lineaires...
    Malgré tout , meme en combinant les formes , les retours sont les memes à chaque execution , cela signifie que la "mecanique" du traitement est fixe pour chaque systeme , exact ?
    L'ordonnancement devient-il visible via des fonctions plus avancées ? ( je pense à une sorte de "timestamp" )

    ( je poste içi ce code , ajout à celui de JeitEmgie , pour visualiser tout ça )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    #include <stdio.h>
     
    void call(int a, int b, int c, int d)
    {
    	printf("%d %d %d %d ",a,b,c,d) ;
    }
     
    int main(int argc, char **argv)
    {
     
    	int i = 0 ;
    	volatile int j = 0 ;
     
     
    	printf("\n< SORTIES DES DIFFERENTES FORMES D'INCREMENTATIONS SUR : int i = 0 >\n\n");
     
    	call(i++, i++, i++, i++) ;
    	printf("pour i = 0 et appels de forme ( i++, i++, i++, i++) resultat i =  %d\n", i) ;
     
    	i = 0 ;
    	call(++i, ++i, ++i, ++i) ;
    	printf("pour i = 0 et appels de forme ( ++i, ++i, ++i, ++i) resultat i =  %d\n", i) ;
     
    	i = 0;
    	call(i++, i++, ++i, ++i) ;
    	printf("pour i = 0 et appels de forme ( i++, i++, ++i, ++i) resultat i =  %d\n", i) ;
     
    	i = 0;
    	call(++i, ++i, i++, i++) ;
    	printf("pour i = 0 et appels de forme ( ++i, ++i, i++, i++) resultat i =  %d\n\n", i) ;
     
    	printf("\n< SORTIES DES DIFFERENTES FORMES D'INCREMENTATIONS SUR : volatile int j = 0 >\n\n");
     
    	call(j++, j++, j++, j++) ;
    	printf("pour j = 0 et appels de forme ( j++, j++, j++, j++) resultat j =  %d\n", j) ;
     
    	j = 0 ;
    	call(++j, ++j, ++j, ++j) ;
    	printf("pour j = 0 et appels de forme ( ++j, ++j, ++j, ++j) resultat j =  %d\n", j) ;
     
    	j = 0;
    	call(j++, j++, ++j, ++j) ;
    	printf("pour j = 0 et appels de forme ( j++, j++, ++j, ++j) resultat j =  %d\n", j) ;
     
    	j = 0;
    	call(++j, ++j, j++, j++) ;
    	printf("pour j = 0 et appels de forme ( ++j, ++j, j++, j++) resultat j =  %d\n\n", j) ;
     
     
     
    	return 0 ;
    }

  9. #9
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par lowbin Voir le message
    Malgré tout , meme en combinant les formes , les retours sont les memes à chaque execution , cela signifie que la "mecanique" du traitement est fixe pour chaque systeme , exact ?
    Tu n'as aucune garantie que ce soit systématique sur un système. En pratique cela risque de dépendre du compilateur utilisé (voire de la version de celui-ci), des options de compilations, des optimisations effectuées sur le code, etc.

Discussions similaires

  1. [C#] Passer des contrôles comme parametre dans une fonction
    Par sara21 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 20/09/2006, 13h05
  2. oublier volontairement des parametres dans une fonction
    Par Joe Le Mort dans le forum Langage
    Réponses: 2
    Dernier message: 23/08/2006, 16h12
  3. fonction récupérant des valeurs dans une fonction popup...
    Par petitsims dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 20/01/2005, 14h51
  4. Réponses: 6
    Dernier message: 24/12/2004, 16h46
  5. [langage] Passage de paramètres dans une fonction
    Par And_the_problem_is dans le forum Langage
    Réponses: 11
    Dernier message: 28/06/2004, 08h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo