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 :

Allocation de Pointeur de pointeur de structure


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Fooshi
    Homme Profil pro
    ICD
    Inscrit en
    Juin 2002
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ICD
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2002
    Messages : 508
    Par défaut Allocation de Pointeur de pointeur de structure
    Bonjour,
    j'essaye d'allouer l'espace pour un pointeur de pointeur de structure.
    Voici ma structure en question contenant le pointeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct sql_result
    {
    	int 						nrows;				// Number of rows returned by the query.	
    	int 				  		ncolumns;			// Number of columns returned by row description.
    	struct sql_att_desc		    att_desc [SQL_ATT_DESC_MAX_VALUE];	// Array of row description.
    	struct sql_att_value	 ** rows;				// Each sql_result is an array of sql_att_value.
    	int 				 		row_array_size;		// Allocated size of rows array.
    	int 				 		binary;				// Binary row values if binary == 1, otherwise Text.
    };
    l'allocation que j'essaye de faire dans une fonction init :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct sql_att_value ** rows;
    rows = (struct sql_att_value **) malloc(SQL_ATT_VALUE_MAX_VALUE * sizeof(struct sql_att_value *));
    mais j'ai l'impression que mon allocation est mauvaise car lorsque je veux acceder a un de mes elements comme ceci, ca plante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sql_conn->result->rows[sql_conn->result->nrows]->len = 128
    quelle est la bonne syntaxe pour cette allocation memoire ? merci d'avance

  2. #2
    Membre chevronné Avatar de seeme
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    430
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 430
    Par défaut
    Bonjour,

    Je précise: je débute dans le donnage de conseil en C++, la suite est à prendre avec des pincettes (pas de compilo sous la main)..

    Mais j'ai toujours suivit cette structure (je crois que le cast d'un malloc n'est pas toujours obligatoire).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #define MAX_STRUCT 16
     
    maStruct **pStructure;
    int i = 0;
     
    pStructure = malloc(MAX_STRUCT * sizeof(void*));
     
    for(i; i < MAX_STRUCT; ++i)
        pStructure[i] = malloc(sizeof(maStruct));

  3. #3
    Membre éclairé Avatar de Fooshi
    Homme Profil pro
    ICD
    Inscrit en
    Juin 2002
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ICD
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2002
    Messages : 508
    Par défaut
    tu veux dire ce cast la ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pStructure = (struct maStruct *) malloc(MAX_STRUCT * sizeof(void*));

    Merci ceci fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct sql_att_value ** rows;
     
    rows = malloc(SQL_ATT_VALUE_MAX_VALUE * sizeof(struct sql_att_value *));
    		for (i = 0; i < SQL_ATT_VALUE_MAX_VALUE; i++)
    		{
    			rows[i] = malloc(sizeof(struct sql_att_value));
    		}
     
    sql_conn->result->rows = rows;
    comment tout initialiser mon pointeur de pointeur avec bzero ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bzero(sql_conn->result->rows, SQL_ATT_VALUE_MAX_VALUE * sizeof(struct sql_att_value *));
    cette ligne me casse tout , une boucle est preferable ?

  4. #4
    Membre chevronné Avatar de seeme
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    430
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 430
    Par défaut
    Je ne suis pas sûr de voir ce que que tu veux faire...


    Mettre les pointeurs à null, pourquoi pas, ça permet de vérifier que l'alloc s'est bien passée.

    Si c'est bien ce que tu veux faire?

    Logiquement, malloc réserve une zone mémoire contiguë, donc ça devrait marcher...

    Où est cette ligne? Quel est le message d'erreur? Juste un segfault?


    Pour le cast du malloc... malloc retourne un void* cad un pointeur. J'ai l'impression qu'il y a plusieurs écoles à ce propos, disons que faire le cast permet peut-être un typage plus fort (je dis ça, j'en sait rien, je me suis pas vraiment posé la question, en général je cast..).

  5. #5
    Membre éclairé Avatar de Fooshi
    Homme Profil pro
    ICD
    Inscrit en
    Juin 2002
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ICD
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2002
    Messages : 508
    Par défaut
    Par habitude je caste aussi, j'ai terminé mon allocation, ca donne ca :

    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
    struct sql_att_value ** rows;
     
    ows = (struct sql_att_value **) malloc(SQL_ATT_VALUE_MAX_VALUE * sizeof(struct sql_att_value *));
    		for (i = 0; i < SQL_ATT_VALUE_MAX_VALUE; i++)
    		{
    			rows[i] = malloc(sizeof(struct sql_att_value));
    		}
    		if (check_not(rows == NULL, "Can't alloc rows"))
    		{
    			return -1;
    		}
    sql_conn->result->rows = rows;
     
    for (i = 0; i < SQL_ATT_VALUE_MAX_VALUE; i++)
    	{
    		bzero(sql_conn->result->rows[i], sizeof(struct sql_att_value));	
    	}

  6. #6
    Membre chevronné Avatar de seeme
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    430
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 430
    Par défaut
    Ce qui suit ça me parait plus juste...

    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
    struct sql_att_value ** rows;
     
    rows = (struct sql_att_value **) malloc(SQL_ATT_VALUE_MAX_VALUE * 
    sizeof(struct sql_att_value *));
     
    if (check_not(rows == NULL, "Can't alloc rows"))
        return -1;
     
    		for (i = 0; i < SQL_ATT_VALUE_MAX_VALUE; i++)
    		{
    			rows[i] = malloc(sizeof(struct sql_att_value));
                            if (check_not(rows[i] == NULL, "Can't alloc rows"))
                                return -1;
    		}
     
    sql_conn->result->rows = rows;

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    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 815
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par seeme Voir le message
    Pour le cast du malloc... malloc retourne un void* cad un pointeur. J'ai l'impression qu'il y a plusieurs écoles à ce propos, disons que faire le cast permet peut-être un typage plus fort (je dis ça, j'en sait rien, je me suis pas vraiment posé la question, en général je cast..).
    C'est historique

    A l'origine, malloc() était prototypé en char*. Renvoyant un pointeur sur un caractère, il était alors impératif de caster son retour en pointeur sur le type qu'on voulait. Ne serait-ce que pour pouvoir ensuite utiliser *valeur_de_retour et récupérer le bon type.

    Ensuite est arrivé le pointeur universel "void *". Universel signifie "s'adapte à tout" (et aussi "ne correspond à rien de précis").
    Le "ne correspond à rien de précis" signifie que si on a en main un "void *pt", on ne pourra pas aller taper dans "*pt" car personne ne sait ce qu'il y a. A la limite, "*pt" pourrait être considéré de type "void" donc "vide" mais il faut plus voir cette phrase comme une métaphore que comme une norme.

    Le "s'adapte à tout" signifie que pt peut être recopié sans aucun souci dans n'importe quel pointeur. Une fois qu'il sera recopié, l'élément pointé pourra alors lui-aussi être récupéré et manipulé.
    Ainsi, puisque malloc() renvoie maintenant un "void *", rien n'interdit de copier ce qu'il renvoie dans n'importe quel pointeur sans avoir à faire de cast.

    On pourrait toutefois se dire "oui mais le cast ne dérange personne". Hé ben si, malheureusement il dérange...
    Déjà, il est inutile et écrire des trucs inutiles ne glorifie pas le programmeur qui le fait (pourtant, j'avoue à ma grande honte écrire encore parfois return(x) et sizeof(x) au lieu de return x et sizeof x). Bon, ok, l'argument de l'inutilité est un piètre argument
    Toutefois, et c'est là le plus important, le cast, si on le met, force le compilateur à faire la conversion même si le type retourné par malloc n'est pas "void *". Si par exemple on oublie d'inclure <stlib.h>, malloc ne sera alors plus prototypé. Le compilo, en le voyant pour la première fois dans le code le considèrera alors de type "int" (type par défaut) et transformera alors tous ses retours en int. Puis, le cast transformera cet int en pointeur sans que le compilo n'y trouve à redire quoi que ce soit.
    Alors ça marchera tant que les int et les pointeurs ont la même taille. Puis le jour où ça changera

    Voilà pourquoi il ne faut plus caster le malloc.
    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]

  8. #8
    Membre émérite Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    On pourrait toutefois se dire "oui mais le cast ne dérange personne". Hé ben si, malheureusement il dérange...
    Autre fois je déconseillais aussi le cast du retour de malloc(), mais aujourd'hui je ne vois aucun argument qui tient la route, pour moi c'est plus une question d'habitude.

    Citation Envoyé par Sve@r Voir le message
    Toutefois, et c'est là le plus important, le cast, si on le met, force le compilateur à faire la conversion même si le type retourné par malloc n'est pas "void *".
    malloc retourne toujours un void*.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void *malloc(size_t size);
    Citation Envoyé par Sve@r Voir le message
    Si par exemple on oublie d'inclure <stdlib.h>, malloc ne sera alors plus prototypé. Le compilo, en le voyant pour la première fois dans le code le considèrera alors de type "int" (type par défaut) et transformera alors tous ses retours en int. Puis, le cast transformera cet int en pointeur sans que le compilo n'y trouve à redire quoi que ce soit.
    Alors ça marchera tant que les int et les pointeurs ont la même taille. Puis le jour où ça changera
    Si ton compilateur est incapable de te prévenir, alors il faut le changer d'urgence ! Au pire il suffit de le régler en fouillant dans les options de compilations (niveau d'alerte).

    P.S: Je n'ai jamais casté le retour de malloc().

Discussions similaires

  1. Pointeurs et pointeurs de pointeurs
    Par wallace27 dans le forum C
    Réponses: 10
    Dernier message: 09/04/2015, 22h07
  2. Réponses: 11
    Dernier message: 01/08/2010, 14h34
  3. Réponses: 21
    Dernier message: 06/08/2009, 09h31
  4. Réponses: 6
    Dernier message: 26/05/2007, 00h33
  5. Réponses: 6
    Dernier message: 02/11/2006, 16h44

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