Quelques bizzareries en C, Où le code ne fait pas ce qu'il suggère |
Bienvenue invité ( Connexion | Inscription )
Quelques bizzareries en C, Où le code ne fait pas ce qu'il suggère |
19 Mar 2022, 19:58
Message
#1
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 |
Hello toutes et tous les codeurs en C,
J'ai vu passer un tweet provocateur sur le C, qui avait relaxé son typage à la manière de JavaScript. Code jaypee@MacMini2018JP LangageC % alias bat bat='gcc -w' jaypee@MacMini2018JP LangageC % cat ./typesRelaches.c #include <stdio.h> int main() { puts("-0.5" + 1); } jaypee@MacMini2018JP LangageC % bat -o typesRelaches typesRelaches.c jaypee@MacMini2018JP LangageC % ./typesRelaches 0.5 Puis il a eu dans le même relâchement des règles, l'adoption par C de l'exponentiation de Fortran, **: Code jaypee@MacMini2018JP LangageC % cat exposant.c #include <stdio.h> int main() { printf("%d\n", 50 **"2"); } jaypee@MacMini2018JP LangageC % bat -o exposant exposant.c jaypee@MacMini2018JP LangageC % ./exposant 2500 Enfin, on peut annoncer toujours dans cette même réforme du langage, un nouvel opérateur "tend vers" --> : Code jaypee@MacMini2018JP LangageC % cat tendVers.c #include <stdio.h> int main() { int x = 5; while (x --> 0) { printf("%d ", x); } printf("\n"); } jaypee@MacMini2018JP LangageC % bat -o tendVers tendVers.c jaypee@MacMini2018JP LangageC % ./tendVers 4 3 2 1 0 Mais, tout ça n'est en fait que fake news, Il y a une entourloupe, bien sûr ! Sauriez-vous rétablir la vérité ? Crédits: la Twitteuse @lunasorcery Ce message a été modifié par Jaypee - 19 Mar 2022, 20:01. |
|
|
19 Mar 2022, 23:33
Message
#2
|
|
Terminaltor Moderating Machine Groupe : Admin Messages : 24 454 Inscrit : 25 Oct 2002 Lieu : Jeumont (59) Membre no 4 319 |
Le premier affiche la chaine "-0.5" à partir du 2e caractère (addition à un pointeur)
Le deuxième déréférence la chaîne char* "2" (*"2" = '2' = 0x32 = 50) La troisième c'est juste l'opérateur de décrément post-fixé (x-- = x-1) ^^ -------------------- I think therefore I Mac
|
|
|
20 Mar 2022, 09:34
Message
#3
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 |
Bravo Schlum,
Mais je n'en attendais pas moins de la vielle garde :-) On peut peut-être diluer un peu pour les débutants en C. Leçon n°1, C se fiche de la présentation: Code int ... est une instruction correcte en C.x = 5; Leçon n°2, un pointeur est un doublet (adresse, type) L'incrémentation de 1 du pointeur donne pour résultat le pointeur (adresse + sizeof(type), type) Dans ces exemples, il faut se rappeler qu'en C, il n'existe pas de type primitif "string", et on l'implémente par un pointeur sur caractère: char * text. Dans les encodages occidentaux, en général, un caractère occupe un octet, et sa taille est 1. Donc dans l'exemple n°1, on a une chaîne littérale (une valeur isolée, non attachée à un identificateur), comme 1, ou 0. Cette chaîne a néanmoins une certaine adresse, et "-0.5" + 1, ne fait qu'incrémenter de 1 l'adresse de la chaîne, c'est-à-dire, on saute le signe -. On utilise un "puts", car un "printf" aurait facilement trahi cette esbroufe. C'est aussi la raison de l'alias pour "gcc -w" qui " mange" tous les warnings qui auraient tout de suite donné l'alerte. Ne jamais compiler avec -w. La leçon n°1 est applicable à l'exemple n°2 : on n'a pas d'opérateur **, mais une multiplication suivie de la déréférence d'un pointeur. La déréférence consiste à interpréter la mémoire à l'adresse du pointeur, en utilisant la taille du type, pour obtenir une valeur de ce type. * appliquée à un pointeur de caractère donne la valeur du caractère à cette adresse. Le chiffre 2, dans la table ASCII est à la position 50, et en C, caractère ou entier non-signé, c'est pareil. donc '2' == 50. Une manière simple de convertir un chiffre représenté en caractère, de '0' à '9', en sa valeur numérique est : Code int n; char c; c = '2'; n = c - '0'; // Note : '0' == 48 printf("%d\n", n); Donc l'exemple n°2 calcule en fait 50 * 50. Note : Si on déclare des structs avec des champs : Code struct personnage { int force; int age; } si on déclare un personnage directement, le point permet d'accéder au champ "age" : Code personnage merlin; merlin.force = 1000; merlin.age = 500; int age = merlin.age; et si on déclare un pointeur sur un personnage : Code personnage *pMagicien; pMagicien = (personnage *)malloc(sizeof(personnage)); après qu'on a alloué la mémoire pour contenir les données, et qu'on a rempli la structure avec les données, on utilisera la flèche pour combiner * et .: Code pMagicien -> age = 200; pMagicien -> force = 100; Note plus avancée : Attention, il existe aussi la notion de handle, un pointeur sur un pointeur (de type adresse, taille selon la CPU), sur un type primitif ou défini dans les déclarations : Code Window **hWindow; Leçon n°1 de nouveau, pour l'exemple n°3, --> n'existe pas comme opérateur. Avec des parenthèses supplémentaires, on aurait écrit: Code while((x--) > 0) Un gros tampon [BUSTED] donc en travers de ces fake news ! JP Ce message a été modifié par Jaypee - 24 Mar 2022, 07:55. |
|
|
Nous sommes le : 27th September 2024 - 11:05 |