Variable locale détruite lors de l'appel de bsearch ?
7 réponses
Michel
Bonjour,
J'ai enfin trouvé comment résoudre mon problème d'exception lors de
l'appel à bsearch.
Il fallait remplacer la variable locale char coupleLettres[3];
par une variable/zone mémoire allouée dynamiquement.
Mais je cherche à comprendre ce qui se passait avec le tableau de char
comme variable locale.
Est-ce que cette variable était détruite lors de l'appel à bsearch ou
lors de l'appel à la fonction de comparaison ou c'est une autre raison ?
Ci dessous le code qui fonctionne bien et celui qui génèrait l'exception.
Michel
/* copie du couple de lettre dans la zone mémoire allouée
dynamiquement*/
strncpy(pCoupleLettres, pCaractereTrouve + 3,
LONGUEUR_COUPLE_LETTRES);
pCoupleLettres[2] = '\0';
/* recherche du couple de lettres dans le tableau */
if(bsearch(&pCoupleLettres,
pInfosFichierIni_t->pTabIdPub,
pInfosFichierIni_t->nbElement,
sizeof(char*), ComparerChaine) != NULL)
idPub = VRAI;
}
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Randolf Carter
Salut,
Le plantage dans le cas du tableau déclaré sur la stack provient d'une erreur d'adressage. Le tableau local n'est absolument pas détruit, il est bel et bien alloué sur la pile et reste présent tant que l'on reste dans des fonctions appelées par ta fonction VerifierChampsPub().
L'origine du souci, c'est ta fonction de comparaison... int ComparerChaine(const void *chaine1, const void *chaine2) { return strcmp(*(char**) chaine1, *(char**) chaine2); } ...qui demande des pointeurs sur des pointeurs de caractères -> char **.
Dans le cas de l'allocation dynamique, tu passes bien un char ** : char *pCoupleLettres; bsearch(&pCoupleLettres, [...]); En d'autres termes, le type de &pCoupleLettres est bien char **.
Dans le cas du tableau local ce n'est pas le cas : char coupleLettres[3]; bsearch(&coupleLettres, [...]); Il est impossible d'obtenir l'adresse de l'adresse de coupleLettres. coupleLettres est *déjà* l'adresse de tes caractères sur la pile, et demander l'adresse de son adresse n'a pas de sens. C'est un peu subtile à comprendre, mais avec un peu de réflexion cela vient tout seul ;-) Tu peux vérifier ce que je raconte en comparant le résultat des expressions coupleLettres et &coupleLettres : tu verras que tu obtiendras le même résultat. Exemple : char *p = coupleLettres; /* Récupère l'adresse du premier caractère */ char *q = &coupleLettres; /* Récupère l'adresse de coupleLettres */ Et à coup sûr p == q. Car l'adresse de coupleLettres sur la pile *est* l'adresse de son premier caractère. C'est pour cela que demander l'adresse de son adresse est impossible.
Pour résoudre ton problème sans passer par une allocation dynamique injustifiée (c'est lourd pour ce que tu en fais), il suffit de passer par une variable locale intermédiaire dont tu pourras prendre l'adresse. Exemple : char coupleLettres[3]; [...] char *p = coupleLettres; bsearch(&p, [...]); Là tu as bien un char ** (un pointeur p, pointant sur l'adresse d'un tableau de char).
-- À plus, - Randolf Enlever les X de mon adresse pour me répondre directement.
Salut,
Le plantage dans le cas du tableau déclaré sur la stack provient d'une
erreur d'adressage. Le tableau local n'est absolument pas détruit, il est
bel et bien alloué sur la pile et reste présent tant que l'on reste dans des
fonctions appelées par ta fonction VerifierChampsPub().
L'origine du souci, c'est ta fonction de comparaison...
int ComparerChaine(const void *chaine1, const void *chaine2)
{
return strcmp(*(char**) chaine1, *(char**) chaine2);
}
...qui demande des pointeurs sur des pointeurs de caractères -> char **.
Dans le cas de l'allocation dynamique, tu passes bien un char ** :
char *pCoupleLettres;
bsearch(&pCoupleLettres, [...]);
En d'autres termes, le type de &pCoupleLettres est bien char **.
Dans le cas du tableau local ce n'est pas le cas :
char coupleLettres[3];
bsearch(&coupleLettres, [...]);
Il est impossible d'obtenir l'adresse de l'adresse de coupleLettres.
coupleLettres est *déjà* l'adresse de tes caractères sur la pile, et
demander l'adresse de son adresse n'a pas de sens. C'est un peu subtile à
comprendre, mais avec un peu de réflexion cela vient tout seul ;-)
Tu peux vérifier ce que je raconte en comparant le résultat des expressions
coupleLettres et &coupleLettres : tu verras que tu obtiendras le même
résultat.
Exemple :
char *p = coupleLettres; /* Récupère l'adresse du premier caractère */
char *q = &coupleLettres; /* Récupère l'adresse de coupleLettres */
Et à coup sûr p == q. Car l'adresse de coupleLettres sur la pile *est*
l'adresse de son premier caractère. C'est pour cela que demander l'adresse
de son adresse est impossible.
Pour résoudre ton problème sans passer par une allocation dynamique
injustifiée (c'est lourd pour ce que tu en fais), il suffit de passer par
une variable locale intermédiaire dont tu pourras prendre l'adresse. Exemple
:
char coupleLettres[3];
[...]
char *p = coupleLettres;
bsearch(&p, [...]);
Là tu as bien un char ** (un pointeur p, pointant sur l'adresse d'un tableau
de char).
--
À plus,
- Randolf
Enlever les X de mon adresse pour me répondre directement.
Le plantage dans le cas du tableau déclaré sur la stack provient d'une erreur d'adressage. Le tableau local n'est absolument pas détruit, il est bel et bien alloué sur la pile et reste présent tant que l'on reste dans des fonctions appelées par ta fonction VerifierChampsPub().
L'origine du souci, c'est ta fonction de comparaison... int ComparerChaine(const void *chaine1, const void *chaine2) { return strcmp(*(char**) chaine1, *(char**) chaine2); } ...qui demande des pointeurs sur des pointeurs de caractères -> char **.
Dans le cas de l'allocation dynamique, tu passes bien un char ** : char *pCoupleLettres; bsearch(&pCoupleLettres, [...]); En d'autres termes, le type de &pCoupleLettres est bien char **.
Dans le cas du tableau local ce n'est pas le cas : char coupleLettres[3]; bsearch(&coupleLettres, [...]); Il est impossible d'obtenir l'adresse de l'adresse de coupleLettres. coupleLettres est *déjà* l'adresse de tes caractères sur la pile, et demander l'adresse de son adresse n'a pas de sens. C'est un peu subtile à comprendre, mais avec un peu de réflexion cela vient tout seul ;-) Tu peux vérifier ce que je raconte en comparant le résultat des expressions coupleLettres et &coupleLettres : tu verras que tu obtiendras le même résultat. Exemple : char *p = coupleLettres; /* Récupère l'adresse du premier caractère */ char *q = &coupleLettres; /* Récupère l'adresse de coupleLettres */ Et à coup sûr p == q. Car l'adresse de coupleLettres sur la pile *est* l'adresse de son premier caractère. C'est pour cela que demander l'adresse de son adresse est impossible.
Pour résoudre ton problème sans passer par une allocation dynamique injustifiée (c'est lourd pour ce que tu en fais), il suffit de passer par une variable locale intermédiaire dont tu pourras prendre l'adresse. Exemple : char coupleLettres[3]; [...] char *p = coupleLettres; bsearch(&p, [...]); Là tu as bien un char ** (un pointeur p, pointant sur l'adresse d'un tableau de char).
-- À plus, - Randolf Enlever les X de mon adresse pour me répondre directement.
Michel
Dans le cas du tableau local ce n'est pas le cas : char coupleLettres[3]; bsearch(&coupleLettres, [...]); Il est impossible d'obtenir l'adresse de l'adresse de coupleLettres. coupleLettres est *déjà* l'adresse de tes caractères sur la pile, et demander l'adresse de son adresse n'a pas de sens. C'est un peu subtile à comprendre, mais avec un peu de réflexion cela vient tout seul ;-) Tu peux vérifier ce que je raconte en comparant le résultat des expressions coupleLettres et &coupleLettres : tu verras que tu obtiendras le même résultat. Exemple : char *p = coupleLettres; /* Récupère l'adresse du premier caractère */ char *q = &coupleLettres; /* Récupère l'adresse de coupleLettres */ Et à coup sûr p == q. Car l'adresse de coupleLettres sur la pile *est* l'adresse de son premier caractère. C'est pour cela que demander l'adresse de son adresse est impossible.
Si j'ai bien compris : coupleLettres étant le nom du tableau, c'est donc une constante et une constante n'a pas d'adresse. C'est pour cela qu'il est impossible d'obtenir l'adresse de l'adresse de coupleLettres?
Pour résoudre ton problème sans passer par une allocation dynamique injustifiée (c'est lourd pour ce que tu en fais),
Oui, ça je l'avais remarqué, mais ça permettait au moins de résoudre mon problème d'exception.
il suffit de passer par une variable locale intermédiaire dont tu pourras prendre l'adresse. Exemple : char coupleLettres[3]; [...] char *p = coupleLettres; bsearch(&p, [...]); Là tu as bien un char ** (un pointeur p, pointant sur l'adresse d'un tableau de char).
Effectivement, ça fonctionne bien. Merci bcp. Michel
Dans le cas du tableau local ce n'est pas le cas :
char coupleLettres[3];
bsearch(&coupleLettres, [...]);
Il est impossible d'obtenir l'adresse de l'adresse de coupleLettres.
coupleLettres est *déjà* l'adresse de tes caractères sur la pile, et
demander l'adresse de son adresse n'a pas de sens. C'est un peu subtile à
comprendre, mais avec un peu de réflexion cela vient tout seul ;-)
Tu peux vérifier ce que je raconte en comparant le résultat des expressions
coupleLettres et &coupleLettres : tu verras que tu obtiendras le même
résultat.
Exemple :
char *p = coupleLettres; /* Récupère l'adresse du premier caractère */
char *q = &coupleLettres; /* Récupère l'adresse de coupleLettres */
Et à coup sûr p == q. Car l'adresse de coupleLettres sur la pile *est*
l'adresse de son premier caractère. C'est pour cela que demander l'adresse
de son adresse est impossible.
Si j'ai bien compris :
coupleLettres étant le nom du tableau, c'est donc une constante et une
constante n'a pas d'adresse.
C'est pour cela qu'il est impossible d'obtenir l'adresse de l'adresse de
coupleLettres?
Pour résoudre ton problème sans passer par une allocation dynamique
injustifiée (c'est lourd pour ce que tu en fais),
Oui, ça je l'avais remarqué, mais ça permettait au moins de résoudre mon
problème d'exception.
il suffit de passer par
une variable locale intermédiaire dont tu pourras prendre l'adresse. Exemple
:
char coupleLettres[3];
[...]
char *p = coupleLettres;
bsearch(&p, [...]);
Là tu as bien un char ** (un pointeur p, pointant sur l'adresse d'un tableau
de char).
Effectivement, ça fonctionne bien.
Merci bcp.
Michel
Dans le cas du tableau local ce n'est pas le cas : char coupleLettres[3]; bsearch(&coupleLettres, [...]); Il est impossible d'obtenir l'adresse de l'adresse de coupleLettres. coupleLettres est *déjà* l'adresse de tes caractères sur la pile, et demander l'adresse de son adresse n'a pas de sens. C'est un peu subtile à comprendre, mais avec un peu de réflexion cela vient tout seul ;-) Tu peux vérifier ce que je raconte en comparant le résultat des expressions coupleLettres et &coupleLettres : tu verras que tu obtiendras le même résultat. Exemple : char *p = coupleLettres; /* Récupère l'adresse du premier caractère */ char *q = &coupleLettres; /* Récupère l'adresse de coupleLettres */ Et à coup sûr p == q. Car l'adresse de coupleLettres sur la pile *est* l'adresse de son premier caractère. C'est pour cela que demander l'adresse de son adresse est impossible.
Si j'ai bien compris : coupleLettres étant le nom du tableau, c'est donc une constante et une constante n'a pas d'adresse. C'est pour cela qu'il est impossible d'obtenir l'adresse de l'adresse de coupleLettres?
Pour résoudre ton problème sans passer par une allocation dynamique injustifiée (c'est lourd pour ce que tu en fais),
Oui, ça je l'avais remarqué, mais ça permettait au moins de résoudre mon problème d'exception.
il suffit de passer par une variable locale intermédiaire dont tu pourras prendre l'adresse. Exemple : char coupleLettres[3]; [...] char *p = coupleLettres; bsearch(&p, [...]); Là tu as bien un char ** (un pointeur p, pointant sur l'adresse d'un tableau de char).
Effectivement, ça fonctionne bien. Merci bcp. Michel
Randolf Carter
Si j'ai bien compris : coupleLettres étant le nom du tableau, c'est donc une constante et une constante n'a pas d'adresse. C'est pour cela qu'il est impossible d'obtenir l'adresse de l'adresse de coupleLettres?
C'est un peu ça, mais pas vraiment. coupleLettres désigne une zone mémoire de 3 octets sur la pile (un tableau de 3 chars), et tu accèdes à tes caractères grace aux expressions coupleLettres[0], coupleLettres[1] et coupleLettres[2]. Parfait. Lorsque tu déclares n'importe quelle autre variable locale, c'est à peu près le même principe. Par exemple si j'écris long i; le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile, j'utilise l'expression &i. De même, si je veux l'adresse de mon tableau sur la pile, j'utilise l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un pointeur sur i ? Impossible. Tu n'as nul part une zone mémoire (variable ou autre) stockant l'adresse de i dont tu pourrais prendre l'adresse. Pour le tableau coupleLettres c'est la même chose. Il n'y a nul part une zone mémoire contenant sont adresse. C'est pour cela qu'il faut passer par une variable intermédiaire, dans laquelle on place l'adresse du tableau, afin de prendre l'adresse de cette variable...
J'espère que c'est plus clair maintenant ;-)
-- À plus, - Randolf Enlever les X de mon adresse pour me répondre directement.
Si j'ai bien compris :
coupleLettres étant le nom du tableau, c'est donc une constante et une
constante n'a pas d'adresse.
C'est pour cela qu'il est impossible d'obtenir l'adresse de l'adresse de
coupleLettres?
C'est un peu ça, mais pas vraiment.
coupleLettres désigne une zone mémoire de 3 octets sur la pile (un tableau
de 3 chars), et tu accèdes à tes caractères grace aux expressions
coupleLettres[0], coupleLettres[1] et coupleLettres[2]. Parfait.
Lorsque tu déclares n'importe quelle autre variable locale, c'est à peu près
le même principe. Par exemple si j'écris
long i;
le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés
sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile,
j'utilise l'expression &i.
De même, si je veux l'adresse de mon tableau sur la pile, j'utilise
l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un
pointeur sur i ?
Impossible. Tu n'as nul part une zone mémoire (variable ou autre) stockant
l'adresse de i dont tu pourrais prendre l'adresse.
Pour le tableau coupleLettres c'est la même chose. Il n'y a nul part une
zone mémoire contenant sont adresse. C'est pour cela qu'il faut passer par
une variable intermédiaire, dans laquelle on place l'adresse du tableau,
afin de prendre l'adresse de cette variable...
J'espère que c'est plus clair maintenant ;-)
--
À plus,
- Randolf
Enlever les X de mon adresse pour me répondre directement.
Si j'ai bien compris : coupleLettres étant le nom du tableau, c'est donc une constante et une constante n'a pas d'adresse. C'est pour cela qu'il est impossible d'obtenir l'adresse de l'adresse de coupleLettres?
C'est un peu ça, mais pas vraiment. coupleLettres désigne une zone mémoire de 3 octets sur la pile (un tableau de 3 chars), et tu accèdes à tes caractères grace aux expressions coupleLettres[0], coupleLettres[1] et coupleLettres[2]. Parfait. Lorsque tu déclares n'importe quelle autre variable locale, c'est à peu près le même principe. Par exemple si j'écris long i; le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile, j'utilise l'expression &i. De même, si je veux l'adresse de mon tableau sur la pile, j'utilise l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un pointeur sur i ? Impossible. Tu n'as nul part une zone mémoire (variable ou autre) stockant l'adresse de i dont tu pourrais prendre l'adresse. Pour le tableau coupleLettres c'est la même chose. Il n'y a nul part une zone mémoire contenant sont adresse. C'est pour cela qu'il faut passer par une variable intermédiaire, dans laquelle on place l'adresse du tableau, afin de prendre l'adresse de cette variable...
J'espère que c'est plus clair maintenant ;-)
-- À plus, - Randolf Enlever les X de mon adresse pour me répondre directement.
Michel
Par exemple si j'écris long i; le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile, j'utilise l'expression &i. De même, si je veux l'adresse de mon tableau sur la pile, j'utilise l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un pointeur sur i ?
Ok, je pense avoir compris : Si je déclare UNIQUEMENT : int i = 10; Je peux bien sûr afficher l'adresse de i avec l'opérateur &. i étant une case mémoire d'adresse &i, cette adresse N'A PAS D'ADRESSE.
Pour obtenir l'adresse de l'adresse de i (c'est à dire l'adresse de '&i'), je n'ai pas d'autre choix que DE CREER une variable de type pointeur qui contiendra l'adresse de l'adresse de &i; ce qui donne :
int i = 10; int *pAdresseDeI = &i; int **AdresseDeAdresseDeI = &pAdresseDeI;
J'ai bon là?
Impossible. Tu n'as nul part une zone mémoire (variable ou autre) stockant l'adresse de i dont tu pourrais prendre l'adresse. Pour le tableau coupleLettres c'est la même chose. Il n'y a nul part une zone mémoire contenant sont adresse. C'est pour cela qu'il faut passer par une variable intermédiaire, dans laquelle on place l'adresse du tableau, afin de prendre l'adresse de cette variable...
J'espère que c'est plus clair maintenant ;-)
Ah oui, c'est bien expliqué. Merci bcp. Michel
Par exemple si j'écris
long i;
le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés
sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile,
j'utilise l'expression &i.
De même, si je veux l'adresse de mon tableau sur la pile, j'utilise
l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un
pointeur sur i ?
Ok, je pense avoir compris :
Si je déclare UNIQUEMENT :
int i = 10;
Je peux bien sûr afficher l'adresse de i avec l'opérateur &.
i étant une case mémoire d'adresse &i, cette adresse N'A PAS D'ADRESSE.
Pour obtenir l'adresse de l'adresse de i (c'est à dire l'adresse
de '&i'), je n'ai pas d'autre choix que DE CREER une variable de type
pointeur qui contiendra l'adresse de l'adresse de &i; ce qui donne :
int i = 10;
int *pAdresseDeI = &i;
int **AdresseDeAdresseDeI = &pAdresseDeI;
J'ai bon là?
Impossible. Tu n'as nul part une zone mémoire (variable ou autre) stockant
l'adresse de i dont tu pourrais prendre l'adresse.
Pour le tableau coupleLettres c'est la même chose. Il n'y a nul part une
zone mémoire contenant sont adresse. C'est pour cela qu'il faut passer par
une variable intermédiaire, dans laquelle on place l'adresse du tableau,
afin de prendre l'adresse de cette variable...
Par exemple si j'écris long i; le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile, j'utilise l'expression &i. De même, si je veux l'adresse de mon tableau sur la pile, j'utilise l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un pointeur sur i ?
Ok, je pense avoir compris : Si je déclare UNIQUEMENT : int i = 10; Je peux bien sûr afficher l'adresse de i avec l'opérateur &. i étant une case mémoire d'adresse &i, cette adresse N'A PAS D'ADRESSE.
Pour obtenir l'adresse de l'adresse de i (c'est à dire l'adresse de '&i'), je n'ai pas d'autre choix que DE CREER une variable de type pointeur qui contiendra l'adresse de l'adresse de &i; ce qui donne :
int i = 10; int *pAdresseDeI = &i; int **AdresseDeAdresseDeI = &pAdresseDeI;
J'ai bon là?
Impossible. Tu n'as nul part une zone mémoire (variable ou autre) stockant l'adresse de i dont tu pourrais prendre l'adresse. Pour le tableau coupleLettres c'est la même chose. Il n'y a nul part une zone mémoire contenant sont adresse. C'est pour cela qu'il faut passer par une variable intermédiaire, dans laquelle on place l'adresse du tableau, afin de prendre l'adresse de cette variable...
J'espère que c'est plus clair maintenant ;-)
Ah oui, c'est bien expliqué. Merci bcp. Michel
Yves ROMAN
Par exemple si j'écris long i; le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile, j'utilise l'expression &i. De même, si je veux l'adresse de mon tableau sur la pile, j'utilise l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un pointeur sur i ?
Ok, je pense avoir compris : Si je déclare UNIQUEMENT : int i = 10; Je peux bien sûr afficher l'adresse de i avec l'opérateur &. i étant une case mémoire d'adresse &i, cette adresse N'A PAS D'ADRESSE.
Pour obtenir l'adresse de l'adresse de i (c'est à dire l'adresse de '&i'), je n'ai pas d'autre choix que DE CREER une variable de type pointeur qui contiendra l'adresse de l'adresse de &i; ce qui donne :
int i = 10; int *pAdresseDeI = &i; int **AdresseDeAdresseDeI = &pAdresseDeI;
J'ai bon là?
Oui.
Une adresse n'existe que pour une variable (au sens 'zone mémoire contenant des données'). Une adresse est une donnée. Donc &i existe, est une donnée, et n'a pas d'adresse. Il faut donc utiliser une autre variable pouvant contenir une adresse ( pointeur) et la remplir avec cette donnée. L'adresse de cette variable est alors l'adresse d'une variable contenant l'adresse d'une autre variable contenant un entier.
Par exemple si j'écris
long i;
le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés
sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile,
j'utilise l'expression &i.
De même, si je veux l'adresse de mon tableau sur la pile, j'utilise
l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un
pointeur sur i ?
Ok, je pense avoir compris :
Si je déclare UNIQUEMENT :
int i = 10;
Je peux bien sûr afficher l'adresse de i avec l'opérateur &.
i étant une case mémoire d'adresse &i, cette adresse N'A PAS D'ADRESSE.
Pour obtenir l'adresse de l'adresse de i (c'est à dire l'adresse
de '&i'), je n'ai pas d'autre choix que DE CREER une variable de type
pointeur qui contiendra l'adresse de l'adresse de &i; ce qui donne :
int i = 10;
int *pAdresseDeI = &i;
int **AdresseDeAdresseDeI = &pAdresseDeI;
J'ai bon là?
Oui.
Une adresse n'existe que pour une variable (au sens 'zone mémoire contenant des
données').
Une adresse est une donnée.
Donc &i existe, est une donnée, et n'a pas d'adresse.
Il faut donc utiliser une autre variable pouvant contenir une adresse ( pointeur) et la remplir avec cette donnée.
L'adresse de cette variable est alors l'adresse d'une variable contenant
l'adresse d'une autre variable contenant un entier.
Par exemple si j'écris long i; le symbole i me sert à accéder au 4 octets (sur un système 32bits) réservés sur la pile pour mon entier. Pour obtenir l'adresse de i sur la pile, j'utilise l'expression &i. De même, si je veux l'adresse de mon tableau sur la pile, j'utilise l'expression &coupleLettres.
Maintenant comment ferais-tu pour obtenir un long ** pointant sur un pointeur sur i ?
Ok, je pense avoir compris : Si je déclare UNIQUEMENT : int i = 10; Je peux bien sûr afficher l'adresse de i avec l'opérateur &. i étant une case mémoire d'adresse &i, cette adresse N'A PAS D'ADRESSE.
Pour obtenir l'adresse de l'adresse de i (c'est à dire l'adresse de '&i'), je n'ai pas d'autre choix que DE CREER une variable de type pointeur qui contiendra l'adresse de l'adresse de &i; ce qui donne :
int i = 10; int *pAdresseDeI = &i; int **AdresseDeAdresseDeI = &pAdresseDeI;
J'ai bon là?
Oui.
Une adresse n'existe que pour une variable (au sens 'zone mémoire contenant des données'). Une adresse est une donnée. Donc &i existe, est une donnée, et n'a pas d'adresse. Il faut donc utiliser une autre variable pouvant contenir une adresse ( pointeur) et la remplir avec cette donnée. L'adresse de cette variable est alors l'adresse d'une variable contenant l'adresse d'une autre variable contenant un entier.
Horst Kraemer
On Fri, 26 Dec 2003 17:20:10 +0100, Michel <noSpam> wrote:
Bonjour,
J'ai enfin trouvé comment résoudre mon problème d'exception lors de l'appel à bsearch. Il fallait remplacer la variable locale char coupleLettres[3]; par une variable/zone mémoire allouée dynamiquement. Mais je cherche à comprendre ce qui se passait avec le tableau de char comme variable locale. Est-ce que cette variable était détruite lors de l'appel à bsearch ou lors de l'appel à la fonction de comparaison ou c'est une autre raison ?
Ton problème est le suivant: Tu as un pointeur vers le premier élément d'un tableau de pointeurs vers char (représenté ici par un tableau de pointeur vers char) et tu veux compararer les pointeurs en comparant les chaines vers lesquelles ces pointeurs pointent. Pour les comparer de facon symmétrique (en utilisant une fonction de comparaison qui traite le premier pointeur (clé) et le deuxième pointeur (élément) de la même facon - c.a.d. comme char** - il faut que le pointeur "clé" fourni comme premier paramètre à bsearch soit aussi un pointeur vers pointeur vers char.
et échoue. La raison est que l'expression &ctab ne donne *pas* l'adresse d'un pointeur vers char qui pointe vers 'd' - parce qu'un tableau n'est *pas* un pointeur (tu conais le sermon?) mais &ctab est l'adresse du tableau ctab qui est en même temps l'adresse du premier caractère de ctab, c.a.d. l'adresse du 'd' dans "def". Il y a toujours l'identité
(void*)&tab = (void*)tab;
quand 'tab' est un tableau (!!!).
[ Je répète: Le problème est que l'expression 'tab' est en général convertie en un pointeur constant qui pointe vers le premièr élément de 'tab' - sauf dans une expression comme &tab our sizeof tab. Quand on prend l'adresse d'un tableau, le résultat n'est *pas* un pointeur vers un pointeur constant qui pointe vers le premier élement de 'tab' mais simplement l'adresse de 'tab' "en personne". La conversion automatique tableau->pointeur n'a *pas* lieu quand on prend l'adresse d'un tableau (&tab) ou la taille d'un tableau (sizeof tab). ]
Donc à l'intérieur de 'compars' la transformation
*(char**)(void*)(&k) == *(char**)(void*)k
interprète un pointeur qui pointe vers un char comme un (char**) et l'expression ci-dessus donne un char et non un pointeur vers char.
Il y deux remèdes sans introduire une allocation dynamique pour la clè.
1) Utiliser la fonction asymmétrique compara ci-dessus qui traite le premier paramètre comme char*. C'est possible pour bsearch (et non pour qsort!) parce que le premier paramètre dans la fonction de comparaison est toujours identique au premier paramètre de bsearch:
bsearch(ctab,a,3,sizeof *a,compara);
2) Introduire une variable artificielle pc comme ci-dessus et appeler
bsearch(&pc,a,3,sizeof *a,compars);
en utilisant la fonction de comparaison symmétrique compars. Maintenant &pk est un vrai pointeur vers pointeur vers char parce que maintenant
*(char**)(void*)&pc
est un pointeur vers le 'd' dans "def".
IMHO l'utilisation d'une allocation dynamique est la solution la mois élégante.
-- Horst
On Fri, 26 Dec 2003 17:20:10 +0100, Michel <noSpam> wrote:
Bonjour,
J'ai enfin trouvé comment résoudre mon problème d'exception lors de
l'appel à bsearch.
Il fallait remplacer la variable locale char coupleLettres[3];
par une variable/zone mémoire allouée dynamiquement.
Mais je cherche à comprendre ce qui se passait avec le tableau de char
comme variable locale.
Est-ce que cette variable était détruite lors de l'appel à bsearch ou
lors de l'appel à la fonction de comparaison ou c'est une autre raison ?
Ton problème est le suivant: Tu as un pointeur vers le premier élément
d'un tableau de pointeurs vers char (représenté ici par un tableau de
pointeur vers char) et tu veux compararer les pointeurs en comparant
les chaines vers lesquelles ces pointeurs pointent. Pour les comparer
de facon symmétrique (en utilisant une fonction de comparaison qui
traite le premier pointeur (clé) et le deuxième pointeur (élément) de
la même facon - c.a.d. comme char** - il faut que le pointeur "clé"
fourni comme premier paramètre à bsearch soit aussi un pointeur vers
pointeur vers char.
et échoue. La raison est que l'expression &ctab ne donne *pas*
l'adresse d'un pointeur vers char qui pointe vers 'd' - parce qu'un
tableau n'est *pas* un pointeur (tu conais le sermon?) mais &ctab est
l'adresse du tableau ctab qui est en même temps l'adresse du premier
caractère de ctab, c.a.d. l'adresse du 'd' dans "def". Il y a toujours
l'identité
(void*)&tab = (void*)tab;
quand 'tab' est un tableau (!!!).
[
Je répète: Le problème est que l'expression 'tab' est en général
convertie en un pointeur constant qui pointe vers le premièr élément
de 'tab' - sauf dans une expression comme &tab our sizeof tab. Quand
on prend l'adresse d'un tableau, le résultat n'est *pas* un pointeur
vers un pointeur constant qui pointe vers le premier élement de 'tab'
mais simplement l'adresse de 'tab' "en personne". La conversion
automatique tableau->pointeur n'a *pas* lieu quand on prend l'adresse
d'un tableau (&tab) ou la taille d'un tableau (sizeof tab).
]
Donc à l'intérieur de 'compars' la transformation
*(char**)(void*)(&k) == *(char**)(void*)k
interprète un pointeur qui pointe vers un char comme un (char**) et
l'expression ci-dessus donne un char et non un pointeur vers char.
Il y deux remèdes sans introduire une allocation dynamique pour la
clè.
1) Utiliser la fonction asymmétrique compara ci-dessus qui traite le
premier paramètre comme char*. C'est possible pour bsearch (et non
pour qsort!) parce que le premier paramètre dans la fonction de
comparaison est toujours identique au premier paramètre de bsearch:
bsearch(ctab,a,3,sizeof *a,compara);
2) Introduire une variable artificielle pc comme ci-dessus et appeler
bsearch(&pc,a,3,sizeof *a,compars);
en utilisant la fonction de comparaison symmétrique compars.
Maintenant &pk est un vrai pointeur vers pointeur vers char parce que
maintenant
*(char**)(void*)&pc
est un pointeur vers le 'd' dans "def".
IMHO l'utilisation d'une allocation dynamique est la solution la mois
élégante.
On Fri, 26 Dec 2003 17:20:10 +0100, Michel <noSpam> wrote:
Bonjour,
J'ai enfin trouvé comment résoudre mon problème d'exception lors de l'appel à bsearch. Il fallait remplacer la variable locale char coupleLettres[3]; par une variable/zone mémoire allouée dynamiquement. Mais je cherche à comprendre ce qui se passait avec le tableau de char comme variable locale. Est-ce que cette variable était détruite lors de l'appel à bsearch ou lors de l'appel à la fonction de comparaison ou c'est une autre raison ?
Ton problème est le suivant: Tu as un pointeur vers le premier élément d'un tableau de pointeurs vers char (représenté ici par un tableau de pointeur vers char) et tu veux compararer les pointeurs en comparant les chaines vers lesquelles ces pointeurs pointent. Pour les comparer de facon symmétrique (en utilisant une fonction de comparaison qui traite le premier pointeur (clé) et le deuxième pointeur (élément) de la même facon - c.a.d. comme char** - il faut que le pointeur "clé" fourni comme premier paramètre à bsearch soit aussi un pointeur vers pointeur vers char.
et échoue. La raison est que l'expression &ctab ne donne *pas* l'adresse d'un pointeur vers char qui pointe vers 'd' - parce qu'un tableau n'est *pas* un pointeur (tu conais le sermon?) mais &ctab est l'adresse du tableau ctab qui est en même temps l'adresse du premier caractère de ctab, c.a.d. l'adresse du 'd' dans "def". Il y a toujours l'identité
(void*)&tab = (void*)tab;
quand 'tab' est un tableau (!!!).
[ Je répète: Le problème est que l'expression 'tab' est en général convertie en un pointeur constant qui pointe vers le premièr élément de 'tab' - sauf dans une expression comme &tab our sizeof tab. Quand on prend l'adresse d'un tableau, le résultat n'est *pas* un pointeur vers un pointeur constant qui pointe vers le premier élement de 'tab' mais simplement l'adresse de 'tab' "en personne". La conversion automatique tableau->pointeur n'a *pas* lieu quand on prend l'adresse d'un tableau (&tab) ou la taille d'un tableau (sizeof tab). ]
Donc à l'intérieur de 'compars' la transformation
*(char**)(void*)(&k) == *(char**)(void*)k
interprète un pointeur qui pointe vers un char comme un (char**) et l'expression ci-dessus donne un char et non un pointeur vers char.
Il y deux remèdes sans introduire une allocation dynamique pour la clè.
1) Utiliser la fonction asymmétrique compara ci-dessus qui traite le premier paramètre comme char*. C'est possible pour bsearch (et non pour qsort!) parce que le premier paramètre dans la fonction de comparaison est toujours identique au premier paramètre de bsearch:
bsearch(ctab,a,3,sizeof *a,compara);
2) Introduire une variable artificielle pc comme ci-dessus et appeler
bsearch(&pc,a,3,sizeof *a,compars);
en utilisant la fonction de comparaison symmétrique compars. Maintenant &pk est un vrai pointeur vers pointeur vers char parce que maintenant
*(char**)(void*)&pc
est un pointeur vers le 'd' dans "def".
IMHO l'utilisation d'une allocation dynamique est la solution la mois élégante.
-- Horst
Michel
Je répète: Le problème est que l'expression 'tab' est en général convertie en un pointeur constant qui pointe vers le premièr élément de 'tab' - sauf dans une expression comme &tab our sizeof tab. Quand on prend l'adresse d'un tableau, le résultat n'est *pas* un pointeur vers un pointeur constant qui pointe vers le premier élement de 'tab' mais simplement l'adresse de 'tab' "en personne". La conversion automatique tableau->pointeur n'a *pas* lieu quand on prend l'adresse d'un tableau (&tab) ou la taille d'un tableau (sizeof tab).
OK, c'est très clair.
Merci bien. Michel
Je répète: Le problème est que l'expression 'tab' est en général
convertie en un pointeur constant qui pointe vers le premièr élément
de 'tab' - sauf dans une expression comme &tab our sizeof tab. Quand
on prend l'adresse d'un tableau, le résultat n'est *pas* un pointeur
vers un pointeur constant qui pointe vers le premier élement de 'tab'
mais simplement l'adresse de 'tab' "en personne". La conversion
automatique tableau->pointeur n'a *pas* lieu quand on prend l'adresse
d'un tableau (&tab) ou la taille d'un tableau (sizeof tab).
Je répète: Le problème est que l'expression 'tab' est en général convertie en un pointeur constant qui pointe vers le premièr élément de 'tab' - sauf dans une expression comme &tab our sizeof tab. Quand on prend l'adresse d'un tableau, le résultat n'est *pas* un pointeur vers un pointeur constant qui pointe vers le premier élement de 'tab' mais simplement l'adresse de 'tab' "en personne". La conversion automatique tableau->pointeur n'a *pas* lieu quand on prend l'adresse d'un tableau (&tab) ou la taille d'un tableau (sizeof tab).