Bonjour,
Vous pouvez postez ici vos avis, remarques, suggestions sur l'article suivant :
http://rperrot.developpez.com/articles/c/genericite/
NB: Merci de lire ce message avant de poster.
Bonjour,
Vous pouvez postez ici vos avis, remarques, suggestions sur l'article suivant :
http://rperrot.developpez.com/articles/c/genericite/
NB: Merci de lire ce message avant de poster.
Un super tutorial pour aborder ce point si difficile pour ne pas dire pénible du language C
Merci, ça fait plaisir
Merci pour votre tutoriel, je sens qu'il va m'être très utile
Lecture intéressante, bravo et merci.
Je m'étais un peu frotté à la généricité, ou un truc approchant, j'avais trouvé le C assez peu adapté et surtout l'effort coûteux. J'avais décidé de prendre une approche crocolion, par exemple uniquement sur les formats de pixels, en transformant un uint8_t en uint8_t[1].
On demande souvent à un programme écrit en C d'aller vite. Imaginons des fonctions agissant sur des T[n], n connu à l'exécution, ces fonctions intégrant des boucles lourdes (sinon la question de performance n'a pas à être posée). n n'étant pas connu à la compilation, ni le compilateur ni le programmeur ne pourront optimiser en développant les boucles "courtes", par exemple. Si dans la vraie vie, n ne peut prendre que 3 valeurs, 1, 2 et 4, éventuellement une 4eme dans une future version, il sera souvent objectivement plus performant de multiplier les fonctions. Le gros problème, et dans le cas vécu il était réel, c'est que ça casse la centralisation du code. Le préprocesseur peut être une solution. Mais il me semble qu'il est limité, et de toutes façons il me donne des boutons. J'avais préféré utiliser un script (python) pour générer la source C. Ça marche, et même bien, mais il faut dire que j'utilise python au quotidien, que je travaille seul et que j'utilise le plus souvent possible scons. Bon, je m'égare...
J'ai peut-être constaté une imprécision, dans le paragraphe II-B. Je lis "Ainsi, pour notre fonction, ce ne sont pas les variables a et b que nous échangeons mais leur copie". En fait, ce sont des copies des adresses de a et b qui arrivent dans la fonction, et les variables locales correspondantes (paramètres formels ?) qui sont échangées, à toutes fins inutiles.
Egalement, pour la fonctionmême si le lecteur n'est pas censé être débutant, il sera bon d'expliquer (quelques mots, ou deux lignes de code supplémentaires) comment l'appeler. Il me semble qu'il faut créer dans l'appelant des variables pointeur initialisées par les adresses de a et b.
Code : Sélectionner tout - Visualiser dans une fenêtre à part void swap( void * d1 , void * d2 ){...}
Rien à voir avec la généricité, mais il y a souvent des incompréhensions dans ce genre de truc. Le statut de l'opérateur adresse et son rapport avec la notion de pointeur sont parfois mal expliqués. Combien de débutants (et même plus) voient &a comme ce qu'il est, rien d'autre qu'une constante immédiate, au même titre que 12L par exemple ?
Bonjour/Bonsoir;
Le tutoriel est très clair et bien structuré, merci pour votre travail.
Cependant je rencontre une difficulté dans la section II-B, je n'arrive pas à comprendre ce code :
La fonction reçoit 2 pointeurs génériques, ça je saisis, la première instruction aussi, mais quand j'arrive à la deuxième je bloque, je ne sais pas ce que ça fait. J'ai déjà vu quelque chose dont la syntaxe est très proche, en l'occurrence : un cast, c'est peut être la même chose, mais même en admettant cette possibilité je n'arrive pas à comprendre.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 void swap( void * d1 , void * d2 ) { void * tmp; tmp = *(void **)d1; *(void **)d1 = *(void **)d2; *(void **)d2 = tmp; }
Merci de bien détailler.
A+
Le but de la fonction est d'échanger les valeurs pointées par 2 pointeurs génériques passé en paramètre (mais cela, tu l'avais déjà deviné)
Le problème est que l'on ne peut pas déréférencer un pointeur void * et que l'on veut échanger les objets pointés par ces 2 pointeurs.
pour cela, on passe par une "ruse" qui n'est pas très jolie à voie en faisant croire au compilateur que le pointeur void * est un pointeur sur un void *. A ce moment là, on peut déréférencer un pointeur sur un void * puisque l'objet pointé est un void * et plus un void.
La transformation pour indiquer que le void * est en fait un void ** est effectivement un cast. Cela permet d'aider le compilateur (mais pas le lecteur dans ce cas) pour qu'il fasse ce que l'on veut qu'il fasse.
Raymond
Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi
Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
e-verbe Un logiciel de conjugaison des verbes de la langue française.
Ma page personnelle sur DVP.
Merci pour ton explication ram-0000. J'y vois plus clair maintenant .
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager