OVH Cloud OVH Cloud

Question honteuse

27 réponses
Avatar
Stephane Legras-Decussy
bonjour,

j'ai honte poser une question aussi basique
mais je ne dois pas avoir les yeux en face des trous
et je ne comprend pas ce qui ne va pas depuis plusieures heures :

#include <stdio.h>
#include<conio.h>
#include<stdlib.h>


typedef struct
{
int nbr;

}AA;

void init(AA *aa)
{ aa= (AA*)malloc(sizeof(AA));

}


int main(int argc, char *argv[])
{ AA *aa=NULL;

// init(aa); // (1)

aa= (AA*)malloc(sizeof(AA)); // (2)

aa->nbr=10; // (3)

printf("%d\n",aa->nbr);

getch();

free(aa);

return 0;
}


si j'écris la ligne (2), tout va bien, si je remplace par la ligne (1) alors
le prog crash en ligne (3).

pourquoi ??? ça m'énerve de pas trouver...

10 réponses

1 2 3
Avatar
Emmanuel Delahaye
Stephane Legras-Decussy wrote on 23/03/05 :
#include <stdio.h>
#include<conio.h>


Pas standard et probablement inutile

#include<stdlib.h>

typedef struct
{
int nbr;

}AA;

void init(AA *aa)
{ aa= (AA*)malloc(sizeof(AA));


Cast inutile

Modifier un paramètre est souvent le signe d'une erreur de conception.
C'est une fois le plus le cas ici. Je rappelle que les paramètres sont
passés par valeur en C. La valeur originale n'est pas modifiée de cette
façon.

Il faut
- soit retourner la valeur (ma préférence)
- soit passer l'adresse du pointeur et le modifier par indirection.
(AMA moche et compliqué).

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"There are 10 types of people in the world today;
those that understand binary, and those that dont."

Avatar
Emmanuel Delahaye
Pierre Maurette wrote on 23/03/05 :
Oui, mais toujours sans le cas (AA *).
Je ne comprends pas... (fatigue ?)



Manque un 't'... 'sans le cast'...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"There are 10 types of people in the world today;
those that understand binary, and those that dont."


Avatar
Emmanuel Delahaye
Stephane Legras-Decussy wrote on 24/03/05 :
Eric Levenez a écrit dans le message :
BE67A3C6.310DE%
void init(AA **aa)


arf.... merçi pour toutes les réponses...

comme quoi même avec quelques dizaines de milliers
de ligne de C derrière soit, on peut quand même passer
à coté...

je vous dis pas depuis combien de temps ça me bloquait...
:-(


Défini tes paramètres const, et le problème est réglé...

void init(AA *const a)
{
a = malloc (sizeof *a); /* BUG! */

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

.sig under repair


Avatar
gregg
Emmanuel Delahaye wrote:

Modifier un paramètre est souvent le signe d'une erreur de conception.


Vous voulez dire que préconisez l'absence de toute double indirection
(dans les paramètres) ?

Avatar
Nicolas Maupu
void init(AA **aa)


arf.... merçi pour toutes les réponses...

[...]


je vous dis pas depuis combien de temps ça me bloquait...
:-(
C'est clair que c'est chiant ce genre de truc, mais faut penser

à dormir ;)


--
Nico


Avatar
Hamiral
Emmanuel Delahaye wrote:

Modifier un paramètre est souvent le signe d'une erreur de conception.



Vous voulez dire que préconisez l'absence de toute double indirection
(dans les paramètres) ?


Non, mais par définition un paramètre est différent d'un résultat ...
Je suis sur ce point en tout cas entièrement d'accord avec ED.


Avatar
Horst Kraemer
gregg wrote:

Emmanuel Delahaye wrote:

Modifier un paramètre est souvent le signe d'une erreur de conception.


Vous voulez dire que préconisez l'absence de toute double indirection
(dans les paramètres) ?


Non.

void f(int **p)
{
*p = malloc(42);
}

ne change pas le paramètre. Ca change la valeur a laquelle le
parametre pointe et on pourrait toujours déclarer

void f(int ** const p)


on parle d'un "abus" de paramètre comme ceci

unsigned fac(unsigned n)
{
unsigned f=1;
while (n>1) f*=n--;
return f;
}

--
Horst


Avatar
Bruno Jouhier
on parle d'un "abus" de paramètre comme ceci

unsigned fac(unsigned n)
{
unsigned f=1;
while (n>1) f*=n--;
return f;
}


Tout à fait. Ca serait tellement plus propre si C faisait la distinction
entre paramètre et variable locale, et s'il interdisait de réassigner un
paramètre (si le paramètre est déclaré comme T* param, il devrait interdire
de réassigner param mais bien sûr permettre d'assigner *param).. Ca serait
cohérent avec la sémantique de passage d'argument, et ça éviterait des
erreurs stupides comme celle à l'origine de cette discussion.

Et ce problème est loin de disparaître car tous les langages issus de C (C,
C++, Java, C#) perpétuent cette confusion entre paramètre et variable
locale.

La question n'est donc pas honteuse, ce sont les designers de langage qui
devraient avoir honte!

Bruno.

Avatar
cedric
Horst Kraemer wrote:
on parle d'un "abus" de paramètre comme ceci

unsigned fac(unsigned n)
{
unsigned f=1;
while (n>1) f*=n--;
return f;
}



Autant j'étais d'accord sur le fait que la modification d'un paramètre
trahis souvent une erreur de conception, autant je trouve votre exemple
complètement ... abusif !

Si on veut bien, au contraire de M. Bourguet, considérer que
l'architecture des ordis n'est pas une simple vue de l'esprit, le fait
est que les paramètres sont effectivement bien souvent semblables à des
variables automatiques, par construction. Merci aux inventeurs du C de
ne pas avoir tentés de faire croire le contraire !

Avatar
Emmanuel Delahaye
Bruno Jouhier wrote on 25/03/05 :
on parle d'un "abus" de paramètre comme ceci

unsigned fac(unsigned n)
{
unsigned f=1;
while (n>1) f*=n--;
return f;
}


Tout à fait. Ca serait tellement plus propre si C faisait la distinction
entre paramètre et variable locale, et s'il interdisait de réassigner un
paramètre (si le paramètre est déclaré comme T* param, il devrait interdire
de réassigner param mais bien sûr permettre d'assigner *param).. Ca serait
cohérent avec la sémantique de passage d'argument, et ça éviterait des
erreurs stupides comme celle à l'origine de cette discussion.


Je ne dois pas être aussi intégriste ou dogmatique que certains le
prédentent, parce que je ne suis pas d'accord. La solution générale
pour préserver la valeur des paramètres est de les qualifier avec
'const' comme je l'ai déjà exposé. Mais il est des cas rares, mais qui
existent où l'utilisation du paramètre comme variable locale peut avoir
un sens, notammet pour gagner un peu de place en mémoire automatique
sur de petites fonctions simples et évoluant peu... (à l'occasion d'un
refactoring, par exemple)

La question n'est donc pas honteuse, ce sont les designers de langage qui
devraient avoir honte!


Non. Le C reste un modèle d'efficacité et de compacité. Mais comme je
le rappelle souvent:

"C is a sharp tool"

A ne pas mettre entre les mains des débutants complets[1].
Personnellement, je suis passé par le BASIC (un désastre), le Pascal
(la Révélation), et quelques assembleurs (années 85/90...).

-------------
[1] Je précise pour les ânes qui ne savent pas lire...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.


1 2 3