Aller au menu - Aller au contenu

Profil du membre : Maëlan

Informations générales | Communiquer | Activité sur le site | En savoir plus | Signature | Biographie

Informations générales


Avatar
  • Pseudo : Maëlan
  • Groupe : Membres
  • Date d'inscription : Le 22/04/2010
  • Dernière visite : Il y a 10 min
En ligne Maëlan est connecté(e)
 

Communiquer


Activité sur le site

Nombre de messages : 1140
Nombre de tutoriels : 1
Nombre de news : 4

Profil

Aucune information

Signature

© Message rédigé sous la seule propriété intellectuelle de son auteur Maëlan, et protégé contre toute reproduction partielle ou totale par l’ACTA (je vous remercie).
Logo de Xubuntu

Ne pas passer la main à travers l’enclos des loups.
Ne pas nourrir les lamas.
Ne pas utiliser de flash pour photographier les poneys.
Ne pas se moquer des manchots.


Un alias bien pratique : alias Taurre='cat http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf | grep TOPIC'. À ceux qui comprendront. ;)
 

Biographie

Biographies de Zéros (pas le temps de trier, je jette juste le lien vite fait pour le garder sous le coude)


realmagma




La minute de C
Pour se coucher moins bête ce soir



Je ne suis ni professionnel ni étudiant en informatique ; je serais plutôt un « programmeur du dimanche » passionné par le langage C mais qui n’en connaît pas parfaitement toutes les subtilités. Programmeurs d'un certain niveau, vous n'apprendrez donc strictement rien ici, vous pouvez aller perdre votre temps ailleurs. De temps en temps, je découvre un nouvel aspect qui vient approfondir ma connaissance du langage. Ça peut être une petite astuce, une notion théorique, un piège vicieux… Cette partie de ma bio a pour but de présenter brièvement certains de ces aspects aux « petits » programmeurs curieux de mon genre. Au passage, ça me sert de mémo. :-°
Bonne lecture !

Remarque : par la suite, je pourrai citer des extraits de la norme C (la référence absolue, si vous voulez, bien qu'indigeste). Les brouillons les plus à jour de cette norme sont disponibles au format PDF sur le site Open Standards : ici pour le C99 au format PDF, et là pour le C11 (C89, C99 et C11 sont les versions majeures du langage ; comme leur nom l’indique, elles sont parues en 1989, 1999 et 2000 respectivement).


Les nombres à virgule flottante (float,double) et leurs tracas


Secret (cliquez pour afficher)
Tutoriel disponible ici (cette partie était devenue vraiment trop longue pour une bio :p ).



1) Les opérateurs du C, leur priorité et leur associativité


Secret (cliquez pour afficher)
Maintenant intégré dans la FAQ, en mieux !

Le langage C intègre de nombreux opérateurs : 47 en tout ! Certains sont plus fréquents que d'autres, mais tous ont leur utilité. Le tutoriel officiel de M@teo21, comme de nombreux cours pour débutants, ne les présente pas tous car ils ne sont pas utiles pour débuter.

Le tableau ci-dessous les représente tous. Je ne les expliquerai pas ici : soit vous les connaissez, soit vous ne les connaissez pas. Il a surtout pour but de vous offrir une vision d'ensemble et de rappeler leur priorité et leur associativité. En cas de doute, il peut servir de mémo.

Quelques notions préalables  :
  • Chaque opérateur a une ou des opérandes. Les opérandes, ce sont les expressions à partir desquelles on effectue l'opérateur. Par exemple, l'opérateur + nécessite deux opérandes (une avant et une après) : dans A+B, ce sont A et B.

    On dit qu'un opérateur est « unaire » s'il n'a qu'une seule opérande. Par exemple, ++ (comme dans A++) et sizeof (comme dans sizeof(Type)) sont des opérateurs unaires. De même, les opérateurs ayant deux opérandes sont dits « binaires » (rien à voir avec la base 2), et ceux en ayant trois « ternaires » (il n’en existe qu'un en C, l'opérateur ? : qui s’utilise ainsi : A?B:C et qui est simplement appelé opérateur ternaire).

    Certains opérateurs s’écrivent de façon identique (même symbole) mais se différencient par leur nombre d'opérandes (1 ou 2). Il y en a 4 en tout, en voici la liste :
    Symbole Opérateur unaire Opérateur binaire
    Usage Description Usage Description
    + +A signe : détermine le signe
    de l'expression A
    A + B addition ou soustraction : retourne
    la somme ou la différence de A et B
    -A A - B
    * *A indirection : retourne
    la valeur dont l'adresse est A
    A * B multiplication : retourne le produit
    de A et B
    & &A référence : retourne l'adresse
    de la variable A
    A & B ET binaire (opérateur bit-à-bit) :
    retourne l'entier tel que chaque bit
    est à 1 si et seulement si le bit
    correspondant de chaque opérande est à 1

  • La priorité des opérateurs, c’est l’ordre dans lequel il faut les combiner. Par exemple, A + B * C donnera (A + (B * C)) et non ((A + B) * C) car la multiplication est prioritaire sur l’addition et sera donc effectuée avant.
    Pour contourner les priorités (dans notre exemple, si l’on veut effectuer l’addition avant la multiplication), on met des parenthèses : (A + B) * C.

    Le tableau ci-dessous est organisé de telle sorte qu’un opérateur prioritaire sur un autre sera placé plus haut que ce dernier ; deux opérateurs de même priorité seront sur la même ligne.
     
  • L’associativité des opérateurs, c'est le sens dans lequel il faut les lire : de gauche à droite (left to right, ltr) ou de droite à gauche (right to left, rtl). Par exemple, A + B + C + D donnera (((A + B) + C) + D) et non (A + (B + (C + D))) car l’addition est associative à gauche (ltr). Autre exemple : A = B = C (il est possible d'écrire ceci, bien que peu fréquent) est équivalent à (A = (B = C) et non à ((A = B) = C) car l’opérateur d’affectation a une associativité à droite.


Trêve de bavardages, voici enfin le tableau tant attendu !

Priorité et associativité des opérateurs en C
Catégories d'opérateurs Opérateurs Assoc.
appel de fonction, indiçage,
membre de structure,
membre de structure pointée
( ) [ ] . -> ltr →
opérateurs unaires (Type) sizeof --1 ++1 ! ~ - + * & rtl
multiplication, division, modulo * / % ltr →
addition, soustraction + - ltr →
opérateurs binaires de décalage << >> ltr →
opérateurs de comparaison < <= >= > ltr →
== !=
opérateurs binaires & ltr →
^
|
opérateurs logiques && ltr →
||
opérateur conditionnel ? : rtl
opérateurs d'affectation = += -= *= /= %= <<= >>= &= ^= |= rtl
opérateur virgule , 2 ltr →

Remarques :
1 Il existe en fait deux opérateurs d'incrémentation et deux de décrémentation : les opérateurs postfixés (i--, i++) mais aussi les opérateurs préfixés (--i, ++i) qui sont moins connus (voir le chapitre 2 de cette biographie pour plus de détails).
2 L'opérateur virgule (,) est très méconnu des débutants ; le chapitre 3 de cette biographie vous le présente.


Cette page très complète du Wikipedia anglais apporte plus de détail. Elle présente tous les opérateurs du C et du C++, en indiquant s’ils sont surchargeables et comment, ainsi que leur priorité et leur associativité.


2) Les opérateurs d'incrémentation et de décrémentation : ++ et --


Secret (cliquez pour afficher)
Maintenant intégré dans la FAQ !


3) L'opérateur virgule : ,


Secret (cliquez pour afficher)
Pas encore rédigé, repassez plus tard !


4) L'évaluation en « court-circuit »


Secret (cliquez pour afficher)
Pour la suite, je considère que vous connaissez les opérateurs bit-à-bit (bitwise, en anglais) &, | et ^ et logiques && et ||, et que vous savez la différence entre les deux.

Pour présenter l’évaluation en « court-circuit », un exemple :
Code : C
1
if(p!=NULL && p->member==42)   {/*…*/}

Ici, on vérifie que le pointeur p n’est pas nul avant d’accéder à un membre de la structure sur laquelle il pointe.
Mais, me direz-vous ! (Enfin, j’espère que vous le direz, sinon vous risquez de vous noyer dans un océan de bogues incompréhensibles) Si p==NULL, l’expression de droite (p->member==42) est quand même évaluée, et on aura droit à une belle erreur de segmentation !

Eh bien, non ! Car en C comme dans d’autres langages, l’évaluation des opérateurs logiques suit un mécanisme dit de « court-circuit ». Cela signifie que…
Pour le ET logique : lorsque vous faites A && B, B ne sera pas évalué si A est faux (c’est-à-dire s’il vaut 0) : ce n’est pas nécessaire pour connaître la valeur de l’expression entière, qui sera forcément fausse (du fait de la définition du ET logique).
De même pour le OU logique : dans l’expression A || B, B ne sera pas évalué si A est vrai, car le tout sera forcément vrai.
Enfin, on peut dire que l’opérateur ternaire ?: a aussi un comportement de court circuit : dans (condition) ? X : Y, seule une des deux expressions (X ou Y) sera évaluée/exécutée, en fonction du résultat de la condition (X si la condition est vraie, Y si elle est fausse).

L’évaluation en court-circuit a 2 intérêts :
  • Vous pouvez mettre comme 1ère opérande de && ou || une condition sans laquelle l’évaluation de la 2è opérande provoquerait une erreur, comme dans l’exemple ci-dessus ou celui-ci (honteusement pompé de ) :Code : C
    1
    2
    for(i=0; i<n && tab[i]>val; i++) {
       /* on parcourt le tableau tab de taille n en comparant tab[i] à val */ }
    
    Sans le comportement en court-circuit, lorsqu’on arrive à i==n, alors dans la 2è opérande du &&, on accéderait à tab[n], ce qui nous vaudrait une erreur de segmentation (le dernier indice du tableau étant n-1)…
  • Dans certains cas, optimiser son programme. En effet, le comportement de court-circuit n’accélère pas l’exécution de A && B, par rapport au cas où ce comportement serait absent, si A et B sont de simples variables booléennes. Ce serait même le contraire, car le court-circuit impose d’évaluer A puis B successivement, alors que sans ce fonctionnement A et B seraient évalués simultanément (au mieux, les deux sont aussi rapides).
    Cependant, dans le cas de calculs plus complexes (dont des appels de fonctions), vous pouvez potentiellement économiser un calcul coûteux, s’il est en 2è opérande de && ou ||. Par exemple, j’avais écrit une fonction permettant de vérifier une longue série de relations mathématiques, et qui retourne un booléen indiquant si ces relations sont respectées :Code : C
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    int check(void) {
       /* a, b, c, A, B, C, P et S sont des variables (globales) de type double,
          donc tous ces calculs sont très coûteux (surtout ceux avec sin et cos) */
       return (A+B+C == M_PI)           // 1) À noter que j’ai mis les calculs les plus simples …
           && (a+b+c == P)              //…   en premiers.
           && (2*S == a*b*sin(C))
           && (2*S == a*c*sin(B))       // 2) Grâce au court-circuit, la série de calculs …
           && (2*S == b*c*sin(A))       //…   s’arrête dès qu’une relation n’est pas respectée.
           && (a*a == b*b + c*c - 2*b*c*cos(A))
           /*...*/                      // 3) Si toutes les relations sont justes, alors …
           && (sin(A)/a == sin(B)/b) ;  //…   le programme fait tous les calculs jusqu’à la fin.
    }
    


Cependant, cet aspect peut être une source de problèmes si on l’oublie où qu’on ne le connaît pas. En effet, dans le code suivant (si f et g sont deux fonctions) :Code : C
1
if(f() && g())   {/*…*/}
Si f retourne 0, alors g ne sera même pas exécutée ! C'est fâcheux si g fait autre chose que retourner une valeur, c’est-à-dire si elle a un « effet de bord » : modifier une variable, écrire dans un fichier ou sur l’écran… Si l’on se base ensuite sur les effets de bord de g, on risque de mauvaises surprises.


Une petite citation de la norme pour finir :
Citation : norme ISO/IEC 9899 (C99) − 6.5.13 - Logical AND operator
Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares equal to 0, the second operand is not evaluated.

Citation : norme ISO/IEC 9899 (C99) − 6.5.14 - Logical OR operator
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If the first operand compares unequal to 0, the second operand is not evaluated.

Citation : norme ISO/IEC 9899 (C99) − 6.5.15 - Conditional operator
The first operand is evaluated; there is a sequence point after its evaluation. The second operand is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0;


5) Les champs de bits


Secret (cliquez pour afficher)
Maintenant intégré dans la FAQ !



Vous avez encore soif ?


Je n’ai pas encore rédigé toutes les parties que je voulais, donc repassez plus tard si vous voulez la suite ;)

Pour les curieux pas rassasiés, il existe quantité de choses à découvrir !
Si vous avez appris le C avec le tutoriel officiel de ce site, ne vous y limitez pas ! Il est bien pour débuter si l’on n’a jamais programmé de sa vie, mais il est loin d'être complet (ni d’ailleurs très rigoureux).
Il existe par exemple, rien qu’en restant sur le SdZ, plein d'autres tutoriels pour compléter sa connaissance du C. En fait, j’aurais voulu tous les citer, c’est pourquoi je vous invite à consulter la page qui les répertorie (cette catégorie est l’une des mieux fournie du SdZ). Ensuite, voyez plus loin que le bout de votre nez et allez voir sur d'autres sites (le site Developpez.com en particulier propose des cours de qualité et un forum, entre autres).








\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Boâtakodz




Programme complet en fonctionnel en 14 lignes en C


Secret (cliquez pour afficher)
Faites pas attention, ce code me sert parfois pour tous genres de tests, et ça m’évite de le retaper. Donc que je met ici, tout beau tout complet.Code : C - args.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int n, char const* const* a) {
	char wd[1024];
	if(getcwd(wd, sizeof wd / sizeof *wd) == NULL)
		puts("[error when trying to get working directory"
		     " (function `getcwd`).]");
	printf("[current working directory: '%s']\n"
	       "[%u argument%c passed%c]\n", wd, n, n>1?'s':0, n?':':'.');
	for(; *a; ++a)
		puts(*a);
	return EXIT_SUCCESS;
}



Une implémentation de String en C (liste chaînée de char*)


Secret (cliquez pour afficher)
projet en cours (à son rythme paisible), disponible sur le forum C



Comment on fé un virus?


Secret (cliquez pour afficher)
De temps en temps, on croise sur les forum des topics du type :Citation
Bonjour je voudré savoir comment on fai pour créé un virus

nn c pa pour ce ke vous pensé justemen c pour savoir comment ce protégé

Pour ces occasions savoureuses, j’ai une réponse toute prête :Citation
Bonjour,
Pour supprimer définitivement un dossier et tout son contenu, tu as la fonction LMGTFY dont voici le code :Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#define IN char
#define TARGET  "uep nU"
#define REMOVE  "ehc"
#define CHECKREMOVE int
#include <stdio.h>
#define TO  " ed "
#define DO  ".lam ed "
#define CLEAR  "sap tiaref et en "
#define DEL char const*
void clearF(IN FileDel) {putchar(FileDel);}
void ClearD(DEL DirDel) {putchar(DirDel?'\n':0x0000);}
FILE* LMGTFY(const char* DirPath) {
   CHECKREMOVE i;
   DEL DirAction = DO CLEAR REMOVE "r" REMOVE "er" TO TARGET;
   for(i=DirPath?44:-1337; i; --i)
      clearF(*(DirAction+i-1));
   ClearD(DirPath);
   return (FILE*)42;
}
Tu n’as qu’à l’appeler depuis ton main, comme ça : LMGTFY("C:\\WINDOWS"); par exemple, si tu veux supprimer le dossier "C:\WINDOWS" et tout son contenu (excellente idée). Mais attention, LMGTFY(NULL); fait planter tout ton système (on s'est compris ;) ).

OK, ce n’est pas très difficile à décrypter, mais sur le coup je m’étais bien marré à l'écrire.









\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Brouillon


La suite me sert de brouillon, pas la peine de lire :p Secret (cliquez pour afficher)

Biographie



Parties à rédiger


- mot-clé sizeof
- opérateur virgule
- utiliser les opérateurs bit-à-bit au lieu des logiques ?
- sequence point ("point de séquence" ?) pour les effets de bord (cf en.wikipedia.org, et la norme, parties 5.1.2.3 et annex C)
(à relier avec le cas de f(n++), avec celui des virgules en tant qu'opérateur/séparateur, et avec celui de &&, || et ?:)
- type qualifiers (const, volatile, restrict), surtout le dernier (cf ici)

Divers


- lien vers bio uknow






[tuto] Les nombres flottants



Détails à régler


- changer le plan ?
- titres

À faire / Directions futures

par ordre de priorité :
  • détailler les histoires de calculs (ce que je suis en train de faire finalement sur les conseils de mewtow) ; j'avais davantage mis l'accent sur les comparaisons
  • parler du "floating-point environment" (cf header <fenv.h>) et des "floating-point exceptions" : cf norme annexe F
    • évoquer par ailleurs ces macros de comparaison qui sont "quiet" (= ne lèvent pas d'exceptions) contrairement aux opérateurs de comparaison
  • parler des types de précision étendue (cf long double)
  • parler des autres modes de représentation courants (càd non-IEEE) (cf cette page de en.wikipedia)
  • rajouter des exercices (si big-tuto), par ex : retrouver nombre à partir représentation et l'inverse, macros/fonctions isnan, isinf, etc, ...
  • quiet NaN (QNAN) / signaling NaN (NAN) : cf ceci


Big-tuto ?


Citation : Mewtow
Et oui, je te demande de rajouter quelques chose alors que le tutoriel est vraiment en train de gonfler.
Ce qui m’amène à te donner un dernier conseil, très important : ton mini-tutoriel devrait devenir un big-tutoriel.
Pourquoi ? Et bien Parce que ton tutoriel est vraiment énorme, bien trop pour un mini-tutoriel ! Je crois que ça va s'impose vu tout le boulot que tu as fais.

C'est vrai qu'il est très long, mais je ne vois pas de quoi en faire un big-tuto. Ou alors (au choix)...
  • il n'y aurait que 3 chapitres courts (le minimum quoi).
  • on fusionne avec d'autres tutoriels sur le même thème (genre celui "le vrai visage des variables" par exemple) ; mais il faut que leurs auteurs soient d'accord.
  • on rajoute le maximum qu'on peut dire sur le sujet (donc toutes ces histoires de processeurs) en détaillant bien. J'avais encore une liste dans mon brouillon des ajouts possibles à évoquer, mais que je n'ai pas mis parce que ça en faisait trop :
    • → cf liste des directions futures + haut




Nostalgie imbécile


Secret (cliquez pour afficher)
Citation : Maëlan — ancienne signature (2012/02/14)
1 , 2 , 3 « La notion de passoire est indépendante de la notion de trou, et réciproquement. »
Sur le forum, n'oubliez pas…
\tiny\LaTeX pour les formules de maths ;
zCode et indentation pour le code ;
• de marquer votre sujet résoluImage utilisateur.


Quelques points de C [info/C]
Les nombres à virgules en C [info/C]
(30%) Les encodages [info]
(βêta) Numérations & bases numériques [maths]
Petit poney rosema vie, mon œuvre sur le SdZ


Citation : Maëlan — anciennes citations
« Pourquoi faire simple ? » (2010 — 2011)
« Et pourquoi pas ? » (2011/10/16, cf ici pour tout comprendre)
« Insupportable perfectionniste » (2012/02/06)
austérité de rigueur (depuis le 2012/02/14)
« 100 ans ! » (2012/02/29, ben oui, la preuve ; mais comme le SdZ est mal foutu, il n’acceptait plus ma date de naissance après que j’aie dépassé 100 ans…)
« 1000 messages ! » (2012/04/17, comme ça, discrètement)
Retour à l’austérité (2012/04/21)









\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Bonus !


La Longue et Soporifique Histoire de mon Existence
Rendons à César ce qui appartient à César − c'est une biographie, ici.



Vous avez scrollé jusqu’en bas ? Vous avez tout lu ? Petits curieux, vous méritez bien un petit supplément : un extrait exclusif de ma biographie !

Mon Éminemment Intéressante Existence est une repoussante mixture :
  • d’odyssées au pays des Shadoks :p
  • de séances d'exorcisme sur Rubik’s Cube :magicien:
  • de RAM Cleared sur TI :ninja:
  • de kernel panic sur ordinausore :D
  • de tentatives d’initiation artistique… infructueuses :-°
  • d’un humour… particulier :soleil:
  • de ma croisade spirituelle contre l’astrologie :pirate:
  • d’attaques par injection frénétique de smileys : o_O :'( :lol: :honte: :waw: :zorro: :diable: :colere: (un beau cadeau à celui qui m’explique pourquoi le furax est 2 fois plus large que les autres ! podium : 1. SofEvans, 2. Vinm, 3. jolfo qui fait du zèle, et mention chaleureuse pour GuilOooo pour ses captivantes considérations socio-historiques)

Bon je sais c’est pas drôle.