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 :

Stockage d'une valeur de fonction


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2012
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 17
    Par défaut Stockage d'une valeur de fonction
    Bonjour a tous,

    Je suis confronté a un petit problème :

    J'ai une fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char *options_mycat()
    {
        char *os;
        os = "abcde";
        return os;
    }
    Et j'ai un main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        char *opts;
        opts = options_mycat();
        puts(opts);
        return 0;
    }
    Puis j'affiche mon programme dans le terminal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    "
    prompt$ ./a.out
     
    prompt$
    "
    En clair : le résultat de ma fonction ne se stocke pas (du moins pas entièrement) dans ma variable "opts"... Ai-je oublié quelque-chose ?

    Rhoblik.

    PS : Lorsque je fais un "puts(os);" dans ma fonction tout va bien, "abcde" s'affiche correctement.
    PPS : Lorsque je fais un "putchar(opts[0]);" dans mon main, il n'y a d'affiché que le "a" (normal puisque c'est le caractère qui est q l'emplacement 0 de mon char*, mais pourquoi le resultat de la fonction n'est pas stocké entièrement?).
    PPPS : Pour ceux qui veulent avoir le vrai code (write_out(p,p), analyse_param(p), prompt(), et putstr(p) sont des fonction perso qui fonctionnent ^^ ) :
    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
    68
    69
    70
    71
    72
    73
    74
    75
     
    char *options_mycat(int nb, char **params)
    {
    	int i;
    	int y;
    	int x;
    	int j;
    	char opts[3];
    	char *os;
    	int nb_opt;
      	if (nb > 1)
        {
          	x = 0;
          	for (i = 1; (i < nb) && (params[i] != "--") && (params[i] != "-"); i++)
    		{
    			if (params[i][0] == '-')
    			{
    	      		nb_opt++;
    	      		for (y = 1; y < strlen (params[i]); y++)
    	      		{
    	      			if (params[i][y] == 'b' || params[i][y] == 'e' || params[i][y] == 'n')
    	      			{
    						if (option_cat (opts, params[i][y]) == 'N')
    		  				{
    		    				opts[x] = params[i][y];
    		    				x++;
    		  				}
    		  			}
    		  			else
    		  			{
    		  				opts[0] = 'i';
    		  				opts[1] = params[i][y];
    		  				os = opts;
    		  				return os;
    		  			}
    		  		}
    	    	}
    		}
          	if (nb_opt == 0)
    			return "N";
         	os = opts;
          	return os;
        }
      	else
        	return "N";
    }
     
    int	main (int ac, char **av)
    {
    	int i;
    	char *opts;
    	opts = options_mycat(ac, av);
    	if (opts[0] == 'i')
    	{
    		putstr("cat: illegal option -- ");
    		putchar(opts[1]);
    		puts("");
    		puts("usage: cat [-ben] [file ...]");
    	}
    	else
    	{
    		putchar(opts[0]);
    		putchar(opts[1]);
    		putchar(opts[2]);
    		putchar('\0');
    		if (ac > 1)
    			for (i = 1; i < ac; i++)
    			{
    				write_out(analyse_param(av[i]), opts);
    			}
    		else
    			prompt();
    	}
    	return 0;
    }

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    Quand on retourne un pointeur, il faut bien faire attention à l'objet pointé.
    En effet, si l'objet pointé est déclaré comme étant une variable locale, il sera détruit lors du return.
    Ainsi le pointeur pointera sur une zone mémoire non-allouée et générera une segfault.

    Mais "maChaine" n'est pas une variable locale, c'est une constante présente dans le "data segment" du programme qui existe du début à la fin du programme donc je ne pense pas que cela devrait poser problème (?).

    Par contre même si le C permet d'écrire char * chaine = "maChaine", pour éviter les erreurs, je recommanderais plutôt d'écrire const char * chaine = "maChaine".

    Une erreur qui peut arriver c'est de ne pas compiler le bon exécutable, tu peux essayer de rajouter un petit puts("toto");, de faire un clean puis de recompiller pour voir ce que cela donne.

    Sinon l'utilisation d'un débogueur me semble plus qu'approprier pour voir ce qu'il se passe pas à pas.

  3. #3
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    L'exemple marche parfaitement et ne reflète pas le 'vrai' code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char *options_mycat(int nb, char **params)
    {
    ...
    	char opts[3];
    	char *os;
    ...
         	os = opts;
          	return os;
    ....
    Ici tu retournes l'adresse d'une variable locale (&opts[0]) qui est détruite en sortie de la fonction. C'est illégal.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Février 2012
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 17
    Par défaut
    Merci pour vos réponses constructives

    Neckara,
    J'ai déjà fait plein de tests de débogage : mon code fonctionne mais pas comme je veux ^^'
    Quoi qu'il en soit merci pour ta recommandation de déclarer des constantes plutôt que des variables seules.

    diogene,
    Comment puis-je faire, donc, pour retourner tout mon tableau de char (opts[]), étant donné que ma fonction renvoi un char * ? (J'ai chercher le type de retour d'une fonction pour renvoyer un tableau, mais en vain...)
    Je n'ai évidement pas le droit d'utiliser la fonction "malloc()", qui me permettrai de traiter directement un char *. C'est pour cette raison que j'utilise un tableau de char d'ailleurs ^^

    Ça ne ferai pas 'propre' si je déclare ma variable 'opts' en globale ? :/
    Parce que ce serai une solution, non ?


    Rhoblik.

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Pour ne peux-tu pas utiliser malloc() : contrainte d'un enseignant ou de l'environnement cible ?

    Une solution potentielle mais bien sale : déclarer le tableau de manière statique et renvoyer l'adresse de son premier élément. Je ne sais même pas quel comportement ça peut avoir, mais a priori, ça pourrait fonctionner.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Février 2012
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 17
    Par défaut
    Encore merci pour vos réponses.

    Bktero,
    La contrainte concernant le "malloc()" vient bien d'un enseignant ^^

    Je vais donc tester cette solution, et je vous tiens au courant.

    Rhoblik.

  7. #7
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Comment puis-je faire, donc, pour retourner tout mon tableau de char (opts[]), étant donné que ma fonction renvoi un char * ?
    Si j'en juge par la fonction main(), car la solution à cette question dépend de l'utilisation du tableau par la fonction appelante, la solution naturelle serait :
    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
    char *options_mycat(char * opts, int nb, char **params)
    {
    	int i;
    	int y;
    	int x;
    	int j;
    //	char *os; ne sert probablement à rien
    ...
              return opts;
    ...
              return NULL; //  ? peut être au lieu de return "N"
     
     
    int	main (int ac, char **av)
    {
    	int i;
    	char opts[3];
    	char *os = options_mycat(opts, ac, av);
    ....
    (J'ai chercher le type de retour d'une fonction pour renvoyer un tableau, mais en vain...)
    Tu ne peux pas ! Tu peux renvoyer l'adresse de début d'un tableau alloué en statique ou dynamique mais pas en automatique (variable locale). (A noter que si on enfouit le tableau dans une structure, on peut renvoyer une copie de la structure donc du tableau enfoui)

    Ça ne ferai pas 'propre' si je déclare ma variable 'opts' en globale ? :/
    Parce que ce serai une solution, non ?
    Il n'y a pour l'instant aucune raison d'en faire une globale.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Probleme vba pour renvoyer une valeur en fonction de deux criteres
    Par tarif dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 23/04/2008, 19h28
  2. Réponses: 3
    Dernier message: 22/03/2008, 11h48
  3. Réponses: 5
    Dernier message: 09/12/2007, 18h17
  4. Réponses: 15
    Dernier message: 02/05/2007, 18h04
  5. Réponses: 4
    Dernier message: 01/06/2006, 14h58

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