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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Janvier 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Janvier 2016
    Messages : 3
    Par défaut error: passing argument 1 of ‘f’ makes pointer from integer without a cast [-Werror=int-conversion]
    Bonjour,

    J'essaye actuellement de recréer la fonction printf, mais je rencontre quelques problèmes quant à l'utilisation de va_arg, à la compilation j'obtiens les erreurs suivantes:

    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
    In file included from main.h:4,
                     from _printf.c:1:
    _printf.c: In function ‘_printf’:
    _printf.c:26:46: error: passing argument 1 of ‘f’ makes pointer from integer without a cast [-Werror=int-conversion]
       26 |                     nb_char += f(va_arg(ptr, int));
          |                                              ^
          |                                              |
          |                                              int
    _printf.c:26:46: note: expected ‘__va_list_tag *’ but argument is of type ‘int’
    _printf.c:29:46: error: passing argument 1 of ‘f’ from incompatible pointer type [-Werror=incompatible-pointer-types]
       29 |                     nb_char += f(va_arg(ptr, char *));
          |                                              ^
          |                                              |
          |                                              char *
    _printf.c:29:46: note: expected ‘__va_list_tag *’ but argument is of type ‘char *’
    _printf.c:32:46: error: passing argument 1 of ‘f’ makes pointer from integer without a cast [-Werror=int-conversion]
       32 |                     nb_char += f(va_arg(ptr, int));
          |                                              ^
          |                                              |
          |                                              int
    _printf.c:32:46: note: expected ‘__va_list_tag *’ but argument is of type ‘int’
    cc1: all warnings being treated as errors
    Je compile en utilisant gcc -Wall -Wextra -Werror -pedantic -std=gnu89 -Wno-format *.c et pour le coup, j'arrive à comprendre qu'il n'aime pas mais je vois pas comment régler le problème... Voici les différents fichiers


    main.h
    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
    #ifndef MAIN_H
    #define MAIN_H
    #include <stddef.h>
    #include <stdarg.h>
    #include <unistd.h>
     
    /**
     * struct specifier - Struct specifier
     * @specifier: The specifier
     * @f: The function associated
     */
    typedef struct specifier
    {
    	char *spe;
    	int (*f)(va_list);
    } spec;
     
    int _printf(const char *format, ...);
    int print_char(va_list);
    int print_string(va_list);
    int print_integer(va_list);
    int (*get_functions(char s))(va_list);
     
    #endif /* MAIN_H */
    main.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <stdio.h>
    #include "main.h"
     
    int main(void)
    {
        int len;
     
        len = _printf("Let's try to printf a simple sentence.\n");
        _printf("Length:[%d]\n", len);
        return (0);
    }
    print.c
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #include "main.h"
     
    int print_char(va_list arg)
    {
        char c = va_arg(arg, int);
     
    	return (write(1, &c, 1));
    }
     
    int print_string(va_list arg)
    {
        int i, nb_char = 0;
        char *str = va_arg(arg, char *);
     
        for (i = 0; str[i]; i++)
        {
            write(1, &str[i], 1);
            nb_char++;
        }
        return (nb_char);
    }
     
    int nb_columns(int n)
    {
        int len = 1;
     
        while (n / 10)
        {
            n /= 10;
            len *= 10;
        }
        return (len);
    }
     
    int print_integer(va_list arg)
    {
        int nb_char = 0, column, base, c;
        int n = va_arg(arg, int);
     
        if (n < 0)
        {
            if (n == -2147483648)
            {
                base = n;
                n = -(n + 1);
            }
            else
                n = -n;
            write(1, "-", 1);
            nb_char++;
        }
        column = nb_columns(n);
        while (column)
        {
            if (column == 1 && base == -2147483648)
                write(1, "8", 1);
            else
            {
      			c = n / column + '0';
                write(1, &c, 1);
            }
            nb_char++;
            n %= column;
            column /= 10;
        }
        return (nb_char);
    }
    _printf.c
    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
    #include "main.h"
     
    int _printf(const char *format, ...)
    {
        int nb_char = -1;
     
        if (format)
        {
            int (*f)(va_list);
            va_list ptr;
     
            va_start(ptr, format);
            nb_char = 0;
            for (; *format; format++)
            {
                while (*format != '%')
                {
                    write(1, &format, 1);
                    nb_char++;
                }
                format++;
                f = get_functions(*format);
                switch (*format)
                {
                    case 'c':
                        nb_char += f(va_arg(ptr, int));
                        break;
                    case 's':
                        nb_char += f(va_arg(ptr, char *));
                        break;
                    case 'd':
                        nb_char += f(va_arg(ptr, int));
                        break;
                }
            }
            va_end(ptr);
        }
        return (nb_char);
    }
    get_functions.c
    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
    #include "main.h"
    /**
     * get_functions - get the specifier
     * @s: specifier
     * Return: pointer to the function to use
     */
    int (*get_functions(char s))(va_list)
    {
        spec c[] = {
            {"c", print_char},
            {"s", print_string},
            {"%", NULL},
            {"d", print_integer},
            {"i", NULL},
            {"b", NULL},
            {"u", NULL},
            {"o", NULL},
            {"x", NULL},
            {"X", NULL},
            {"S", NULL},
            {"p", NULL},
            {"+", NULL},
            {" ", NULL},
            {"#", NULL},
            {"l", NULL},
            {"h", NULL},
            {"0", NULL},
            {"-", NULL},
            {"r", NULL},
            {"R", NULL},
            {NULL, NULL}
        };
        int i = 0;
     
    	while (i < 22)
    	{
    		if (s == *c[i].spe)
    			return (c[i].f);
    		i++;
    	}
    	return (NULL);
    }
    Merci d'avance pour votre aide !
    Fichiers attachés Fichiers attachés

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Tes fonctions et ton pointeur de fonction sont du type int (*)(va_list), il faut leur passer en argument un va_list, mais la macro va_arg(ptr,T) quant à elle retourne un T et modifie en conséquence la valeur de ptr pour passer au suivant. Ça n'est pas ce qu'il faut passer à la fonction!

    Si tu souhaites que chaque fonction s'occupe de récupérer le paramètre dont elle à besoin, c'est à elle de faire le va_arg(...), et c'est à elle de retourner ce qu'est devenu le ptr modifié par va_arg(). Et lors de l'appel, il suffit de lui passer le ptr et de récupérer son évolution.
    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    va_list  print_char( va_list arg ) {
        const char  c = va_arg( arg, int );
        write(1, &c, 1);
        return  arg;
    }

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Janvier 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Janvier 2016
    Messages : 3
    Par défaut
    Bonjour dalfab,

    Je comprend mieux le problème, toutefois j'aimerais que ma fonction compte le nombre de caractères imprimés, en faisant en sorte que chaque fonction retourne le nombre qu'elle a imprimé. En mettant va_list en argument je ne peux donc pas être à jour du compte ?

    J'ai remarqué également que VSCode met une fonction qui retourne un tableau n'est pas autorisée C/C++(91) [3,9] (je fait en C89 ça doit jouer). J'ai tenté du coup de laisser int et d'incrémenter va_list mais ça me met que ptr n'est pas modifiable.

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Si tu veux garder le retour en int, il faut que ptr soit modifiable, et donc passer son adresse à la place.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int  print_char( va_list* p_arg ) {        // on reçoit l'adresse du va_list
        const char  c = va_arg( *p_arg, int );   // on utilise le va_list
        return  write(1, &c, 1);
    }
    Et à l'utilisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
            int (*f)(va_list*);
            va_list  ptr;
     
            va_start( ptr, format );
            ... ...
                f = get_functions( *format );   // get_functions retourne un int (*)(va_list*)
                switch ( *format ) {
                    case 'c':
                        nb_char += f( &ptr );   // on passe le va_list par adresse
                        break;
            ... ...
    Et une fonction ne peux pas retourner ni recevoir un tableau par valeur. Ça n'est pas nouveau, c'était déjà le cas en 1970.

Discussions similaires

  1. assignment makes pointer from integer without a cast
    Par morpheusmg dans le forum Débuter
    Réponses: 4
    Dernier message: 27/11/2011, 17h31
  2. Réponses: 5
    Dernier message: 17/02/2011, 20h19
  3. Réponses: 2
    Dernier message: 12/11/2010, 12h11
  4. Réponses: 3
    Dernier message: 08/09/2009, 09h40
  5. Réponses: 6
    Dernier message: 11/05/2006, 22h08

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