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 :

Pointeur fonction avec argument pointeur


Sujet :

C

  1. #1
    Nouveau Candidat au Club Avatar de hublott
    Femme Profil pro
    Collégien
    Inscrit en
    Juillet 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2018
    Messages : 4
    Points : 1
    Points
    1
    Par défaut Pointeur fonction avec argument pointeur
    Salutation,

    J'essais de rentre un code plus lisible (il n'y a qu'une seule fonction int main(void) et ça fait trop).

    Sauf que l'argument de cette fonction est un pointeur et la fonction elle même est de type pointeur.
    Quand j'essais de compiler le code et voici les message d'erreurs:

    invalid operands to binary expression
    ('double' and 'double *')
    f = -k* r + b/pow(r, 5);
    ~~^ ~
    error: passing 'double *' to parameter of incompatible type
    'double'; dereference with *
    f = -k* r + b/pow(r, 5);
    ^
    *
    /usr/include/math.h:443:25: note: passing argument to parameter here
    extern double pow(double, double);
    ^

    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
     
    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    #include <time.h>
    #define M 3 // masse du point en kg
    #define k 0.1  // constante kg/sec^2
    #define N 100000   // Nombre d'interation
    #define pi 3.14159
     
     
    double *fonction (double *r) {
        double *f;
        double b= 0.0; 
        f = -k* r + b/pow(r, 5);
        return f;
        }
    Désolée, je ne sais pas si je m'exprime mal, n'hésitez pas à dire vous en pensez..

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Le compilateur te dit tout

    Est-ce que tu sais ce qu'est un déréférencement ? (<- C'est le premier truc qu'on apprend avec les pointeurs)


    En gros lorsque tu codes "k* r" toi tu vois une multiplication, le compilateur voit un déréférencement "*r" et un "k" avant

    Et ensuite la signature de la fonction pow est "(double, double)" et non pas "(double*, double)".

  3. #3
    Nouveau Candidat au Club Avatar de hublott
    Femme Profil pro
    Collégien
    Inscrit en
    Juillet 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2018
    Messages : 4
    Points : 1
    Points
    1
    Par défaut Déréférencement je sais pas trop
    Merci fœtus.

    Concernant le déférencement, je ne vois pas ce que c'est j'ai pas beaucoup été enseigner sur le code.

    Du coup comment différencier une multiplication d'un pointeur dans ma formule ?

    J'ai modifié mon code comme vous pouvez le vois ci dessous mais j'ai encore un message d'erreur :
    error: assigning to 'double *' from incompatible type 'double'
    f = *r * (-k) + b/pow(*r, 5);
    ^ ~~~~~~~~~~~~~~~~~~~~~~~~

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    double *fonction (double *r) {
        double *f;
        double b= 0.0;
        f = *r * (-k) + b/pow(*r, 5);
        return f;
        }

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Désolé mais renseigne toi sur les pointeurs et la programmation en C.

    En gros "double* r" r est un pointeur vers une valeur double et "*r" on déréférence r pour accéder à cette valeur double

    Et ton code est mauvais parce que qui dit pointeur dit pointeur NULL

    Le vrai code est (non testé, non compilé) (sans codes erreur) :
    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
    size_t fonction (double* r, double* result) {
        size_t ret;
     
        if ((r != NULL) && (result != NULL)) {
            double b = 0.0;
     
            (*result) = -(k * (*r)) + b/ pow((*r), 5);
     
            ret = 1;
        } else {
            ret = 0;
        }
     
        return ret;
    }

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par hublott Voir le message
    Concernant le déférencement
    La vraie question devient donc : pourquoi utilises-tu des pointeurs alors que visiblement tu ne les maîtrises pas ? As-tu vraiment besoin de pointeurs pour réaliser ton programme ?

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Pourquoi fonction retourne-t-elle un pointeur? La multiplication de deux flottants retourne un flottant, et non un pointeur.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Nouveau Candidat au Club Avatar de hublott
    Femme Profil pro
    Collégien
    Inscrit en
    Juillet 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2018
    Messages : 4
    Points : 1
    Points
    1
    Par défaut Réponse à Bktero et Médinoc
    Clairement, je ne maîtrise pas du tout les pointeurs (même pas les bases du C) donc pourquoi, bonne question...

    Je devrais peut-être donner mon code dans sa totalité mais en gros.
    L'une des raisons pour laquelle j'utilise un pointeur c'est que j'utilise une variable plusieurs fois dans le code. Selon le peu que j'ai appris sur les pointeurs il faut mettre un objet en mémoire pour le réutiliser (mettre en mémoire et "le pointer" pour appelé l'objet quoi).

    Sauf qu'en faisant mes recherches je me suis rendu compte que je n'ai peut être pas besoin de pointeur!
    En effet, dans le reste de mon code, j'utilise un tableau et moi, on m'avait "appris" que tableau=pointeur or askip, c'est faux (selon Openclasroom).

    Un tableau se comporte comme un pointeur (c'est-à-dire qu'il place les objets en mémoire) mais que ce n'est pas un pointeur

    I am choked, well je suis une brêle en code comme vous l'auriez remarqué et désolée si je m'exprime mal..

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Un tableau est un espace mémoire contigü de taille X*Y où X est la taille du type d'élément que tu veux y mettre et Y le nombre d'éléments que tu veux y mettre.
    Pour accéder à un tableau on utilise généralement un pointeur vers le premier élément, que l'on décallera pour accéder aux éléments suivants.

    Un tableau n'a rien à voir avec un pointeur, il se trouve juste que le pointeur est l'élément le plus pratique (ou le seul ?) pour accéder à ses éléments.

    Un pointeur c'est un schmilblik qui pointe sur quelque chose.
    C'est un machin qui contient une valeur qui est l'adresse de quelque chose (ou NULL) et non une valeur directement interprétable comme double, int, char etc.
    C'est un truc qui aurait une flèche pour montrer où se trouve l'élément derrière.

    Edit: la confusion vient aussi imo du fait que quand on déclare un tableau static int tab[10];, alors tab est le nom du tableau alors qu'il s'agit en fait et surtout d'un pointeur vers le premier élément.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Nouveau Candidat au Club Avatar de hublott
    Femme Profil pro
    Collégien
    Inscrit en
    Juillet 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Collégien
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2018
    Messages : 4
    Points : 1
    Points
    1
    Par défaut Réponse à Bousk
    C'est ce que j'ai lu en effet.

    Je pense que je vais me renseigner plus sur le sujet et pour le code je verrais ultérieurement.

    Merci à tous :)

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par hublott Voir le message
    Selon le peu que j'ai appris sur les pointeurs il faut mettre un objet en mémoire pour le réutiliser (mettre en mémoire et "le pointer" pour appelé l'objet quoi).
    Non pas forcément on peut prendre l'adresse d'une variable avec l'opérateur &.
    Et, j'ai oublié de le dire avant , attention quand même aux variables locales qui sont détruites en fin de fonction/ procédure.

    Et comme tu parles de tableau, il faut juste l'adresse d'une case et l'incrémenter/ décrémenter pour parcourir son tableau.


    Citation Envoyé par hublott Voir le message
    Sauf qu'en faisant mes recherches je me suis rendu compte que je n'ai peut être pas besoin de pointeur!
    En effet, dans le reste de mon code, j'utilise un tableau et moi
    Effectivement, tu peux juste retourner la valeur double et placer ce résultat dans la bonne case. t[current] = fonction(&r); ou (*current_val) = fonction(&r);.
    Et comme ton paramètre est un paramètre d'entrée qui n'est pas une structure/ union tu n'as pas besoin de pointeur pour le transmettre.


    Citation Envoyé par hublott Voir le message
    on m'avait "appris" que tableau=pointeur or askip, c'est faux (selon Openclasroom).
    ...
    Un tableau se comporte comme un pointeur (c'est-à-dire qu'il place les objets en mémoire) mais que ce n'est pas un pointeur
    La différence (à part la syntaxe interchangeable [] et *), c'est qu'on peut déclarer un pointeur avec un type incomplet mais pas un tableau (ce qui est logique)

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par hublott Voir le message
    L'une des raisons pour laquelle j'utilise un pointeur c'est que j'utilise une variable plusieurs fois dans le code. Selon le peu que j'ai appris sur les pointeurs il faut mettre un objet en mémoire pour le réutiliser (mettre en mémoire et "le pointer" pour appelé l'objet quoi).
    Non. Tu as tout à fait le droit d'utiliser la même variable plusieurs fois. C'est d'ailleurs à ça que sert une variable: mémoriser une valeur pour s'en resservir ailleurs (et s'en resservir au-moins deux fois sinon pas besoin de variable).

    Un pointeur, c'est juste un type. Tout comme il y a des types int (pour stocker un entier), float (pour stocker un flottant), char (pour stocker un caractère), il existe un type "pointeur" permettant de stocker une adresse.
    Simplement la règle de nommage diffère un peu car il faut aussi connaitre l'adresse de quoi. C'est donc dans cette optique qu'on écrit char * pour dire "je stockerai ici l'adresse d'une variable de type char" ou double * pour dire "je stockerai ici l'adresse d'une variable de type double". Bref quel que soit le type générique "ttt" de la variable initiale, son adresse est toujours un "ttt étoile" (on rajoute juste "étoile" derrière son type).

    Alors à quoi sert un pointeur: la toute première chose, c'est à faire modifier une variable (située dans une fonction X) par une fonctionY. Comme les variables ne sont que recopiées quand on les passe à une autre fonction, la seule façon possible est de passer l'adresse de la variable à la fonction. La fonction recevant une adresse (enfin une copie mais c'est pareil) la stockera, elle, dans une variable apte à stocker une adresse => un pointeur. Et un pointeur sur le type de la variable passée.
    Exemple: fonction qui initialise un int à 0. La fonction recevra l'adresse de ce "int" donc stockera cette adresse dans un "int étoile"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void init(int *p) {
    	(*p)=0;
    }

    Ecrire int *p dans la déclaration signifie à la fois "p est un pointeur sur un int" et "étoile p (donc l'objet pointé par p) est un int".
    Et dans la fonction, connaissant l'adresse de la variable à initialiser, je peux aller à cette adresse (donc ce qui est pointé par p) et y mettre 0. Accessoirement tu noteras ici une source de confusion: en effet, l'opérateur "étoile" quand il est écrit dans une déclaration de variable signifie "adresse de" et quand il est écrit dans une instruction signifie "pointe vers". Donc à toi de te souvenir de la nuance.

    Et utilisation de cette fonction
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main() {
    	int toto, titi;
    	init(&toto);
    	init(&titi);
    }
    J'envoie l'adresse de "toto" à la fonction ; puis pareil avec l'adresse de "titi". Et à chaque fois, la fonction va à l'adresse en question et (sans même se préoccuper de quelle variable il s'agit) y met 0.

    La seconde chose à quoi sert un pointeur c'est permettre d'itérer sur les éléments d'un tableau. En effet, les éléments d'un tableau sont toujours contigüs en mémoire. C'est une obligation de la norme. Il s'ensuit que si tu connais l'adresse d'un élément du tableau, rien ne t'interdit de regarder ce qu'il y a à cette adresse mais aussi ce qu'il y a à l'adresse suivante, qui correspondra donc à l'élément suivant du tableau. Et grace aux mathématiques des pointeurs, tu n'as même pas besoin de gérer la taille des éléments (un char prend un octet donc s'étale sur une adresse tandis qu'un double s'étale sur 8) car toute opération mathématique sur un pointeur est en réalité calculée sur l'espace utilisé par le type pointé. Si tu ajoutes "1" à l'adresse d'un double, le C transformera ça en ajout de 8 ce qui fait que tu seras toujours placé au début de la variable.

    Exemple
    Code c : 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
    int main() {
    	double tab[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    	double *pt;
    	int i;
     
    	pt=&tab[0]			// Je place l'adresse de "tab[0]" dans "pt"
     
    	// Itération sur les indices du tableau
    	for (i=0; i < 10; i++) {
    		// Affichage en passant par l'indice (façon classique)
    		printf("Le carré de %lf est %lf\n", tab[i], tab[i] * tab[i]);
     
    		// Affichage en passant par le pointeur (ou plutôt le pointé)
    		printf("Le carré de %lf est %lf\n", *pt, (*pt) * (*pt));
     
    		// Il faut incrémenter le pointeur pour qu'il positionne sa valeur sur l'adresse du double suivant
    		pt++;
    	}
     
    	// Autre façon d'écrire le for (en plus condensé)
    	for (i=0, pt=tab /* "tab + n" équivaut à "&tab[n]" donc "tab" équivaut à "&tab[0]" */; i < 10; i++, pt++) {
    		printf("Le carré de %lf est %lf\n", *pt, (*pt) * (*pt));
    	}	// L'initialisation et l'incrément se font dans le for() qui peut très bien gérer plusieurs variables à la fois
    }

    Alors pourquoi utiliser un pointeur alors qu'il existe les indices ? Parce qu'un indice est recalculé à chaque fois. A chaque fois que tu demandes "tab[i]" le C se met au début et calcule "i fois taille d'un élément" (et moi je l'écris 3 fois dans mon printf()). Tandis qu'avec "pt", le pointeur est déjà à la bonne adresse et cette adresse n'est calculée qu'une fois lors de l'incrément.

    De plus, si les éléments du tableau te permettent de créer une sentinelle (valeur spéciale indiquant la fin) alors l'indice devient inutile.
    Admettons par exemple que tu ne travailles qu'avec des nombres naturels, tu peux alors très bien te conventionner avec toi-même comme quoi un négatif sera un flag de fin.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main() {
    	double tab[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1};
    	double *pt;
     
    	for (pt=tab; (*pt) >= 0; pt++) {
    		printf("Le carré de %lf est %lf\n", *pt, (*pt) * (*pt));
    }
    Et hop, plus besoin de gérer une seconde variable collée au tableau comme un poisson pilote. Et (comme le dit certain), "une variable en moins c'est un écu de moins dans la poche du médecin" (ou alors c'est un verre de vin, je me mélange un peu).

    Sinon pour toute autre utilisation des variables (c'est à dire une utilisation simple de leur valeur sans besoin de la modifier) créer un pointeur sur cette variable est inutile. Pire, mettre un pointeur là où on n'en a pas besoin peut te bloquer dans tes actions.
    Exemple: deux fonctions qui calculent le carré d'un nombre. La première écrite de façon classique et la seconde en passant par un pointeur
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    unsigned int carre_classique(int v) {
    	return v*v;
    }
     
    unsigned int carre_ptr(int *pt) {
    	return (*pt)*(*pt);
    }

    Maintenant, je calcule le carré d'une variable

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main() {
    	int toto=123;
    	printf("Le carré de %d est %lu\n", toto, carre_classique(toto));
    	printf("Le carré de %d est %lu\n", toto, carre_ptr(&toto));
    }

    C'est ok. Mais si je veux calculer le carré d'une simple valeur...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int main() {
    	printf("Le carré de 123 est %lu\n", carre_classique(123));
    	printf("Le carré de 123 est %lu\n", carre_ptr(/* OUPS !!! Que vais-je passer à ma fonction ??? */));
    }

    Donc c'est comme pour tout. Les pointeurs ne sont que des outils mais comme tout outil, si on veut qu'il soit efficace il faut l'employer dans le domaine de ses compétences.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. problème de fonction avec des pointeurs
    Par bl4cksky dans le forum Débuter
    Réponses: 16
    Dernier message: 09/09/2013, 12h28
  2. fonction avec argument predefini
    Par duplo dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 29/08/2006, 19h06
  3. onChange et fonction avec arguments
    Par pierre.egaud dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 13/06/2006, 11h02
  4. DLL export de fonction avec argument
    Par slate dans le forum C
    Réponses: 3
    Dernier message: 31/05/2006, 10h36
  5. creer une fonction avec arguments
    Par niglo dans le forum ASP
    Réponses: 3
    Dernier message: 03/06/2005, 08h04

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