298 private links
Un article de Thomas VASSEUR, développeur français chez Motion Twin, boîte française aussi, où il explique pourquoi et comment générer des modèles 3G dans un jeu vidéo en 2D dit "Pixel Art".
Ainsi, je comprends mieux pourquoi ce rendu pixel art, alors que je me dis (peut-être) j’aurais préféré une version non pixel art, comme pour pour le jeu Hollow Knight.
Pour commencer, oui, l’arithmétique des pointeurs dans la programmation actuelle, et globalement l’utilisation du langage C, est quelque chose de plus en plus rare, car la majorité des langages sont dits de haut niveau, ils font abstraction du code machine, et leur typage est dynamique.
Toutefois, le langage C a certains atouts (pas de démonstration, ce n’est pas le but de ce billet), et il est ainsi important de produire du code robuste et modulable.
Prenons le cas où vous devez manipuler à travers les paramètres d’une fonction :
- des listes (une dimension) ;
- des matrices/tableaux (deux dimensions) ;
- des volumes (trois dimensions) ;
- voire autant de profondeurs de pointeurs dont vous avez besoin (x dimensions).
(Exemple et démonstration plus bas)
Pour une allocation de mémoire sur une variable faites à partir de pointeurs d’objets, le comportement est :
mytype *my_variable;
my_variable = malloc(sizeof(mytype));
Mais ensuite, si ce n’est plus un seul niveau de pointeurs, mais plusieurs, il faut donc calculer le nombre de pointeurs à mettre : combien d’astérisques à écrire ? est-ce vraiment utile, i.e "void *" ne suffit-il pas ? ce nombre a-t-il un impact ?
Et si on change de type ? par exemple, à l’intérieur d’une structure, vous ne déclarez pas la variable, du coup, il faut aller chercher le type de la variable en question, ce qui n’est pas forcément facile, et si ça change, vous devez manipuler le code.
Voici une solution : utilisez l’idiomatique suivante :
my_var = malloc(sizeof(*my_var));
Il suffit de remarquer qu’il suffit simplement de rajouter un astéristique par rapport à la variable dans le paramètre de gauche, dans le contenu de l’appel sizeof, et c’est tout.
Exemple, vous avez une matrice de "choses", chose pouvant être un entier, un nombre à virgule, un pointeur, une structure, etc, mais que c’est une donnée ici d’un des paramètres de la fonction, voici le résultat :
void myFunction(mytype my_var) {
…
my_var = malloc(sizeof(my_var));
…
}
void main(void) {
mytype **myMatrix;
myFunction(&myMatrix);
…
}
Exemple et Situation :
Prenons le cas où vous avez déjà une liste d’objets, comme une liste de sommets (“vertex/vertices” en anglais) dans un graphe (“graph”) contenant un nombre important de paramètres et d’informations. Recopier le contenu alors que vous souhaitez manipuler l’objet pour lire et créer d’autres ensembles n’est pas le plus efficace, la mémoire s’en alourdi : il suffit d’appeler le pointeur sur l’objet en question.
Déterminons les enfants d’un sommets dans un graphe, avec les arêtes qui les relient (“edge” en anglais) ; on va donc à partir d’un graphe "g" et d’un sommet "v" recevoir une liste de sommets "listChildren", et le nombre d’éléments de cette liste. Comme indiqué en introduction, on ne cherche pas à recopier les données, mais on cherche à recevoir leurs pointeurs. Pareil pour les éléments passés en paramètres en tant que source d’informations.
Remarque : j’évite au maximum d’avoir des variables globales, et je mets en premier dans les paramètres d’une fonction les données qui seront modifiées.
Remarque : pour simplifier la lecture, on pourrait aussi utiliser un “typedef” pour parler de pointeurs sur les différents objets, comme "pgraph" = "graph ", "pvertex" = "vertex ", etc, mais ça devient lourd à utiliser, et ce n’est pas entièrement pratique si on ne l’utilise pas entièrement.
Nous avons en entrée :
- un "graph my_graph" ;
- un "vertex current_vertex" ;
- une liste de pointeurs de sommets "vertex **my_child" ;
- et une valeur de retour, "int nb_children".
La liste des paramètres de la fonction "childrenVertices" ainsi se compose :
- pour le graphe "g" : graph *g ;
- pour le sommet "v" : vertex *v ;
- pour la liste de sommets, nous allons modifier son contenu, il faut rajouter un pointeur dessus : "vertex ***list_children" ;
- et le paramètre de retour sera un entier "int".
int childrenVertices(vertex **list_children, graph g, vertex *v);
À l’intérieur, l’allocation mémoire pour "list_children" sera :
list_children = malloc(nb_vertices sizeof(**list_children));
et son appel sera :
nb_children = childrenVertices(&my_child, &my_graph, ¤t_vertex);
En conclusion, la fonction "childrenVertices" ne manipule que des pointeurs, ce qui économise beaucoup plus de place par rapport à des données dans des structures (sauf pour les petits types, comme les entiers, qui sont moins volumineux dans une architecture 64 bits (4 octets, soient 32 bits pour un entier relatif "int") que pour un pointeur, 8 octets soient 64 bits en archi 64 bits.
Un ensemble de règles pour avoir du code plus stable en C.
De mon point de vue, je trouve que ça alourdit le code, le compliquant à certains passages (sûrement une question d’habitudes), voire le rend moins portable, mais rend son comportement plus consistent sur de différentes plateformes.
Un point de vue intéressant sur les schémas de coloration syntaxique de nombreux éditeurs de code actuels, en pointant leurs défauts au sujet de la mise en valeur du code.
TL;DR:
- les commentaires devraient être plus visibles ;
- les outils de diff ne devraient pas changer la coloration syntaxique en mettant en rouge les retraits et vert les ajouts.
(texte en anglais)
Un article qui explique les détails dans la domaine de l'optimisation derrière les notations O(1), O(n), O(log(n)), etc.
(voir aussi https://links.thican.net/?YPqV3g)
J'en entends souvent parler, mais je suis semble-t-il un "vieux" de la programmation.
Haha, tant d'anecdotes sur les bugs, voici une liste (exhaustive ?) des bugs qu'il est possible de rencontrer avec un nom qui représente bien leurs conditions.
Tiens tiens, un avis intéressant sur le mode de développement MVC (Model View Controllers).
Hahaha, et vive les Hackathons :-D
(Via Le Hollandais Volant http://lehollandaisvolant.net/index.php?mode=links&id=20131111182602)
Une page web sympa qui regroupe un tableau comparatif entre des commandes et des expressions des différents langages Perl, PHP Python et Ruby. :-)
Un tutoriel pour apprendre les bases du développement réseau en C.
Pour la version en PDF, regardez en bas de page (http://www.inetdoc.net/pdf/socket-c.pdf)
Un ensemble de guides et de livres pour apprendre à développer des processus liés au réseau (et aussi à tuer des dragons ;-))
man 7 capabilities
Peut être ce que tu cherches:
CAP_NET_RAW
- utiliser des sockets RAW et PACKET;
- attacher à n'importe quelle adresse pour un service mandataire transparent.
Un livre qui a reçu une bonne critique, au sujet du développement en C sous GNU/Linux, aussi bien pour les développeurs que pour les administrateurs systèmes.
Il est tout de même orienté vers la lib glibc, et aussi disponible en format numérique (PDF/ePub)
Le saviez-vous ?
PHP – comme d'autres langage – lors de l'évaluation de conditions booléennes, fonctionne en mode "évaluation minimale" (ou appelé "short-circuit evaluation" en anglais http://en.wikipedia.org/wiki/Short-circuit_evaluation).
Grâce à l'ordre des opérateurs booléens, cela permet de ne pas tester l'ensemble des expressions dans une condition.
Exemple :
A && B && C
avec l'opérateur "&&" (AND), B n'est testé que si A est "juste", et C n'est testé que si B est "juste" (sans oublier A).
Par contre, avec "||" (OR), dans l'exemple "A && B || C", c'est "B || C" qui est testé avant A (attention, ce n'est pas valable pour tous les langages), et il faut que B soit "faux" pour que C puisse testé.