Bonjour
Est ce que quelqu'un peut m'expliquer pour quoi on a utilisé deux étoiles au lieu d'une **(**tab) dans la fonction Init suivante :
Code:
1
2
3
4 void Init(double **tab, int nb) { *tab = (double*) malloc(nb*sizeof(double)); }
merci
Version imprimable
Bonjour
Est ce que quelqu'un peut m'expliquer pour quoi on a utilisé deux étoiles au lieu d'une **(**tab) dans la fonction Init suivante :
Code:
1
2
3
4 void Init(double **tab, int nb) { *tab = (double*) malloc(nb*sizeof(double)); }
merci
Tout simplement parce que si on avait mis qu'une seule étoile le code ne fonctionnerait pas.
Il s'agit du problème du passage des paramètres à une fonction. Le langage C ,comme le C++, passent leur paramètres par copie (sauf si on utilise une référence). Par conséquent, tab est une copie d'un pointeur qu'on a passé en paramètres. Si tu enlève une étoile, tu ne fera qu'affecter la copie du pointeur et pas le pointeur original.
Fais un dessin avec des flèches et tu verras, c'est évident.
Le mieux restant d'utiliser les std::vector et new[] et les références si on a pas d'autres choix.
Bonjour,
merci de votre réponse (;) .
cordialement .
Sans les deux * le code est parfaitement fonctionnel. Il n'a peut etre pas le resultat escompté.
Depuis quand c'est fonctionnel ?Citation:
Sans les deux * le code est parfaitement fonctionnel. Il n'a peut etre pas le resultat escompté.
Le code sans l'étoile initialise une variable locale : l'adresse de retour du malloc est perdue à la fin de la fonction. Ca ne peut pas fonctionner à moins d'aller à l'encontre de quelques dizaines d'années de développement en C et C++ : Le passage des paramètres est fait par copie.
Prend un papier et un crayon, ou bien prend un cours mais il est évident que ça ne peut pas fonctionner.
En effet fonctionnel décris manifestement le comportement du programme. Un code qui crash tout le temps est non fonctionnel. un code qui crash de temps en temps est instable. Un code qui ne crash pas est parfaitement fonctionnel.
Malheuresement et je suis d'accord avec toi si on enleve l'étoile la fonction ne sert a rien. A part a générer une fuite mémoire.
Désolé si je ne me suis pas fait comprendre, mais un individu tombant sur ta réponse se fera sans doute une mauvaise idée ( le programme crash ).
Salut,
Le fait est que, si tu ne passe pas un pointeur de pointeur à cette fonction, tu auras peut être un code qui compile, mais tu aura surtout énormément d'autres problèmes, dont, principalement, celui que l'on peut raisonnablement penser que la valeur passée comme paramètre pour nb (selon l'exemple) sera considérée comme... le nombre d'éléments que peut contenir ton tableau.
A partir de là, tu as donc de très grandes chances d'alller taper dans une adresse mémoire invalide (à taille réelle + N) et donc, d'avoir un comportement totalement indéfini, parfois juste inaperçus, parfois clairement problématique.
La première règle à garder en mémoire est donc qu'un code qui compile ne signifie pas un code exempt d'erreur parce qu'il peut simplement... respecter la syntaxe du langage.
Or, à l'extrême limite, je préfère un code qui ne compile pas à un code qui ne fait pas ce que l'on attend de lui, car, au moins, on est prévenu que l'on a fait une erreur (et les messages émis par le compilateur nous permettent généralement de la situer plus ou moins ) ;)
Certes !
Ce n'est à ce que je vois qu'un soucis de vocabulaire. Je peux rappelé que ce code compile parfaitement mais le programme ne crashera pas si on n'utilise pas le tableau. Donc pour moi le code est fonctionnel et c'est uniquement dans ce sens que je parle.
Bien sur sans l'étoile la fonction n'est qu'une absurdité sans nom. De la a dire que le code ne fonctionnera pas c'est un peu beaucoup s'avancer étant donné notre connaissance du code qui pour l'instant se réduit à une seule fonction.
Bref mieux vaut prévenir que guérir et je pense que en effet cela est plus judicieux de classer ce code dans la catégorie des "non fonctionnel".
Tu peux carrément le classer dans la catégorie des codes à très haut risque (pour ne pas dire dans celle des codes qui devraient être interdits), la question n'étant plus de savoir SI l'application plantera, mais QUAND elle le fera, car une chose est sure, elle le fera ;)
Aller prétendre qu'un code est fonctionnel lorsque l'on ne regarde qu'une fonction dont on se rend compte par ailleurs qu'elle va poser un tas de problèmes est de la pure inconscience, car toute fonction ne vaut que... parce qu'elle est utilisée par d'autres ;)
Sur ce point je ne suis pas tout a fais d'accord. Un tas d'expert code des fonctions dont eux seuls comprennent le fonctionnement. Pour donner l'exemple de Carmack et de sa fonction qui calcule l'inverse d'une racine carré, avant que le code soit open source il était le seul detenteur du secret 5 plus ou moin trouvé par son "pote" de NVidia. La fonction cela dit est fortement dépendant de l'architecture et donc peut se trouver instable dans certain cas. Pourtant c'est elle qui à fait son succés.Citation:
car toute fonction ne vaut que... parce qu'elle est utilisée par d'autres
Ce point la aussi me chagrine. Je peux te garantir que un code avec uniquement cette fonction je dis bien uniquement ( sans utiliser le tab ou quoique ce soit" ne plantera à aucune execution.Citation:
la question n'étant plus de savoir SI l'application plantera, mais QUAND elle le fera, car une chose est sure, elle le fera
Sur ce point tu as raison ( je me permets de te tutoyer :s ).Citation:
Tu peux carrément le classer dans la catégorie des codes à très haut risque (pour ne pas dire dans celle des codes qui devraient être interdits)
Et c'est la la clé de la question, Certes le code compile et fonctionne dans certain cas, de l'autre côté c'est la pure inconscience.
Une fonction calculant l'inverse d'une racine carrée ne vaudrait que... parce qu'elle rend un service clairement identifié et... qu'elle est utilisée "par ailleurs" afin de disposer du dit service.
Or, si la fonction ne prenait qu'un pointeur simple, elle ne rendrait pas le service que l'on attend d'elle et ne peut donc, purement et simplement, pas être validée en utilisation, y compris durant la période de tests unitaires.
On ne peut donc absolument pas considérer la fonction comme "fonctionnelle", et ce, quelle que soit le sens que l'on voudra donner au terme: c'est une fonction qui compile parce qu'elle respecte la syntaxe imposée par le langage, mais cela s'arrête là: la fonction est erronée et donc non fonctionnelle (au minimum, car, comme je l'ai dit, elle est même super dangereuse ;))
Il est clair que, si tu n'a que cette seule fonction, elle ne sera jamais exécutée...Citation:
Ce point la aussi me chagrine. Je peux te garantir que un code avec uniquement cette fonction je dis bien uniquement ( sans utiliser le tab ou quoique ce soit" ne plantera à aucune execution.
Mais, si une fonction n'est jamais exécutée, pourquoi "perdre son temps" à la coder :question:
La question n'est donc pas de savoir si elle est exécutée ou non (car, même lorsque tu crées une bibliothèque, tu fournis des fonctions parce que... tu estimes qu'elles seront utiles et donc utilisées) mais quand elle le sera... et avec quel résultat.
Or le seul résultat prévisible de la fonction, quelle que soit l'échéance, est un comportement indéfini ;)
Fais seulement, je ne me sens pas vieux assez pour être vouvoyé :DCitation:
( je me permets de te tutoyer :s ).
Fonctionnel, c'est étymologiquement qui fonctionne : qui réalise sa fonction. Ici ça n'est pas le cas. Au mieux tu as une fuite mémoire si tu ne veux pas utiliser ce qui a été alloué. En règle générale, le code plantera lamentablement (après cette fonction) parce qu'on aura essayé de taper dans une case mémoire qui n'est pas allouée.Citation:
En effet fonctionnel décris manifestement le comportement du programme. Un code qui crash tout le temps est non fonctionnel. un code qui crash de temps en temps est instable. Un code qui ne crash pas est parfaitement fonctionnel.
Ce qui est surtout absurde c'est d'être dans le forum C++ et être en train de discuter d'un problème de C et qui est réglé depuis longtemps en C++ (cf. référence).Citation:
Bien sur sans l'étoile la fonction n'est qu'une absurdité sans nom.
En fait, le secret si tant est qu'on puisse parler de secret était déjà connu à l'avance, tu sais comme qu'il s'agit d'une exploitation d'IEEE 754, et que le résultat était plus ou moins déjà mis en évidence dans d'autres papiers antérieurs. Mais bon dieu Carmack avait LA solution ... ;) du coup on a oublié les autres.Citation:
Pour donner l'exemple de Carmack et de sa fonction qui calcule l'inverse d'une racine carré, avant que le code soit open source il était le seul detenteur du secret 5 plus ou moin trouvé par son "pote" de NVidia.
Pour en revenir à cette fonction, elle marche très bien dans les cas d'utilisation qui ont été prévu par Carmack. (c'est parfaitement décris). D'ailleurs tout ça pour dire qu'il faut absolument indiquer les cas d'utilisation de ses fonctions dans les spécifications (donc notamment dans les commentaires) si ceux-ci ne sont pas explicites.
D'accord avec les deux derniers posts.
Il est évident que sur un forum de C++ on parle de C++ et donc de code réutilisable.Ce que j'essayai de dire est que le résultat de cette fonction sera un crash ou une fuite mémoire simple ou les deux, cela dépend de l'utilisation qui suit l'appel de cette fonction. Ce que je voudrais éviter est que un débutant ( car il s'agit bien de cela ici : aucune offense tout le monde passe par la) pense que fuite mémoire = crash. Beaucoup de code présente des fuites mémoires et ne crash pas si souvent que cela.
Juste la distinction entre fonction trés dangereuse car inutilisable ( en imaginant que sa véritable fonction est d'initialiser un pointeur passé en paramètre) et fonction qui crash lamentablement :
Sentez vous la différence que je veux exposer ?Code:
1
2 int tab[] = { 1,2,3}; tab[3] = 9;
Sa fonction est syntaxiquement correcte, fonctionnel mais ne fais pas ce qu'on lui demande et de plus est dangereuse.
Je me suis permis de chercher la définition du mot " fonctionnel " et il est dit de quelque chose de fonctionnel, quelque chose qui est en état de marche qui fonctionne avec un joli exemple :
Il y a clairement la différence entre " marche - t -il ? " et " marche - t -il bien ?". Dans le premier cas il est à l'arret = non fonctionnel. Dans le second il marche mais nous emene à l'étage erroné = fonctionnel.Citation:
Cet ascenseur marche -t -il ?
Je pense néanmoins que cela reste du chipotage. Les esprits des débutant sont assez fragile nous le savons tous, les mots ont une grande importance à ce stade la.
Tout à fait, ce que tu mets en exergue, c'est la différence entre l'exactitude syntaxique et sémantique.Citation:
les mots ont une grande importance à ce stade la.
cela pourrait fonctionner en retournant l'adresse nouvellement allouée.