Langage C : Résumé IChapitre 2 - Types et variables2.1 Codage en binaire2.2 Mémoire2.3 Variable2.4 Types de base2.5 Déclaration et affectation des variables/constChapitre 3 - Opérateurs3.1 Opérateurs arithmétiques3.1.1 priorités3.1.2 types et domaines de définition3.1.3 Règles de conversion implicites3.1.4 Conversions explicites3.2 Opérateur d'affectation et d'assignation3.3 Opérateurs d'incrémentation3.4 Opérateur virgule3.5 Opérations de comparaison3.6 Opérateurs logiques3.6 Opérateurs bit-à-bit3.7 Opérateurs de décalage de bitChapitre 4 - Entrées / Sorties4.1. Syntaxe de printf()4.1.1 Affichage / saisie4.1.2 printf : syntaxe4.2 spécifications de format4.2.1 Caractères4.2.2 Nombre entiers4.2.3 Nombre à virgule flottante4.2.4 Formats d'affichage4.3 caractères d'échappement4.4 Syntaxe de scanf()Chapitre 5 - Structures de contrôle5.1 Branchement conditionnel5.1.1 ifsyntaxe :5.1.2 if elsesyntaxe :5.1.3 Remarques5.1.4 Styles de codageStyle Kernighan & RichtieStyle Whitesmiths5.1.5 Opérateur ternaire5.1.6 Branchement multiple switchswitch seul Syntaxe : Organigramme :switch + breakSyntaxe :Organigramme:5.1.7 Comparaison switch vs if..else5.2 Boucles5.2.1 Boucle whileSyntaxeStructogrammeRemarques5.2.2 Boucle do..whileSyntaxeStructogrammeRemarques5.2.3 Boucle forSyntaxeStructogrammeRemarquesPrécisionsinitialisation ConditionincrémentFonctionnementEquivalent en boucle while5.2.4 Quelle boucle choisir ?5.3 Instructions de branchement inconditionnels5.3.1 Instruction return5.3.2 Fonction exit(<int>)Autres instructions inconditionnellesFonctionnementChapitre 6 - Fonctions (partie 1)6.1 Notion de fonction6.1.1 Avantages de l'utilisation de fonctions6.1.2 Appel de fonction6.1.3 Définition de fonction6.1.4 Prototype de fonction6.1.5 Valeur retournéeTypes de retoursParamètres formelsParamètre effectifs6.2 Variables locales et globales6.2.1 Visibilité des variablesVariables globalesVariables locales6.2.2 Danger des variables globales6.2.3 Mot-clé static6.3 Organisation de la mémoire
les variables : informations que l'on stocke pour les réutiliser plus tard.
la mémoire : divisée en octets, ce qui est 8 bits qui eux mm 8x 0 ou 1.
on va diviser les infos sur plusieurs octets car on ne peut pas les entrer en entier dedans .
les nombres valent la mm chose peut importe la base. Cela représente le mm nombre de choses
c'est seulement la "traduction" pour notre "langage".
dans un ordinateur, au final, tous les nombres sont en binaire, pcq en hw on a un état électrique "haut" ou "bas".
chaque case mémoire a 8bits d'espace, ainsi qu'une adresse.
mais un variable peut avoir une taille plus grande que 1 octet, elle prendra juste plusieurs bytes dans la mémoire
une variable est un endroit de la mémoire ou on va mémoriser une valeur d'un certain type
d'abord on doit déclarer la variable et on peut optionnellement l'initialiser avec une certaine valeur.
pour la déclaration, on doit indiquer au compilateur le type de nos donnée. Cela permet de définir les opérations autorisées ainsi que la place que prendra les données dans la mémoire, pour pouvoir réserver la bonne taille.
la taille (en byte) est généralement une puissance de 2 : 8, 16, 32, 64 bits
p.ex si on déclare un 'int', c'est une variable de 4byte. Il y aura alors 4 byte dans la RAM qui seront "réservés" à cette variable. quand on modifie la var. on va modifier les 4 bytes alloués à celle-ci dans la ram.
Caractéristiques d'une variable :
Cycle de vie d'une variable:
noms de variable :
ne pas commencer par un chiffre
et on ne peut pas utiliser les mots réservés
utiliser uniquement lowerCamelCase pour les variables
C est un langage à type faible, explicite et statique :
faible :
explicite :
statique :
Types de base :
Types dérivés :
Types des entiers:
Types des nombres à virgules
float (32 bits) : signe : 1bit , exposant : bit 8 bits, mantisse : 23 bits (≈ 7 chiffres significatifs) double (64 bits) signe : 1 bit, exposant : 11 bits, mantisse : 52 bits (≈ 16 chiffres significatifs)
Utiliser des noms de variables explicites
initialiser de préférence les variables à leur déclaration
⚠NE PAS UTILISER #DEFINE !!!!!
éviter aux maximum les constantes littérales
on utilise les opérateurs pour "mélanger" différentes données selon un schéma particulier.
+-*/% (= reste de la division entière)il ne faut pas dépasser les valeurs max et min possible d'une variable
il existe une librairie qui fournit des macros qui donne les valeurs max et min des différents type : <limits.h>
Ces valeurs dépendent de l'implémentation de la machine ou de l'archi du CPU
avec les float ou double, on a les nombres spéciaux suivants :
pour les entier, il n'existe pas de valeurs spéciale, mais certains bits ne sont simplement pas pris en compte.
modification de type réalisée par le programmeur
(<type>) <valeur>
on peut aussi utiliser des suffixes :
. pour doublef pour floatu pour unsignedl pour longi = i + 1 équivalent à i += 1
i = i & j équivalent à i &= j
++ : incrément-- : décrémentil y a à chaque fois, deux possibilités :
++aa++il faudrait toujours utiliser les opérateurs préfixés
<opération1>, ..., <opérationN>
on évalue l'expression1, puis 2 jusqu'à N
la valeur de l'opération virgule est celle de la dernière valeur, la plus à droite
par exemple pour une boucle for :
for(int i=0, j=0; i<15; ++i, j+=2)
==!=> (>=)< (<=)les opération de comparaison renvoient toujours soit true (1) soit false (0)!
exemple :
int a = 10 < 20; --> a vaut 1
int a = 10 > 20; --> a vaut 0
&&||!exemple :
bool a = true || false--> a vaut true
bool a = true && false--> a vaut false
Le membre de droite n'est évalué que si nécessaire. par exemple :
bool a = false && true, on n'évalue QUE false parce que dans un AND, les deux opérandes doivent être à true, donc comme le 1er vaut false, peu importe la valeur de la 2e opérande, la condition est fausse.
&|^~on compare chaque bit de la 1re opérande avec chaque bit de la 2e opérande, un par un.
par exemple :
int a = 0101 & 1100; a vaut 0100
a << ba >> ba <<= ba >>= baffichage d'information à l'écran : printf()
saisie de valeur à partir du clavier : scanf()
pour utiliser ces fonctions, il faut inclure la bibliothèque stdio.h : #include <stdio.h>
printf("<chaine de commande>", <Liste d'expressions>);
<chaine de commandes>
hello world%d\nListe d'expressions
La liste d'expressions doit posséder (au moins) autant de valeurs qu'il y a de spécifications de format
Exemple :
xxxxxxxxxx21nb = 20;2printf("nb %d x %d\n", nb, 5+2);renvoie : nb 20 x 7
%c type : char%s type : char*%d type : int%x type : int%p type : void *%f type : float/double%e (%E) type : float/doubleil existe encore d'autres types mais qui ne sont que rarement utilisés.
Avec le type char :
%c affiche le caractère Z%d affiche son code ASCII : 90Avec les types réels, il est possible de donner des indications sur la largeur et la précision de la valeur.
La Largeur L fixe le nombre de caractère minimum que devra prendre notre nombre. Si la largeur est plus grande que la place que prend le nombre, des espaces sont affichés avant le nombre. La largeur comprend tous les caractères que devra afficher le nombre au minimum (valeurs décimales et point compris!)
La précision P fixe la précision, càd le nombre de décimales de notre nombre. La précision commence toujours par un point. La spécification .P indique que P décimales seront affichées.
%<L>.<P>f ou %<L>d par exemple.
exemple :
xxxxxxxxxx71float n = 123.4567;2
3printf("%f", n); // 123.45674printf("%6.1f", n); // _123.4 ( _ = espace)5printf("%2.2f", n); // 123.45 (la largeur L est un minimum !)6printf("%.3f", n); // 123.456 (on ne précise que la précision)7printf("%10f", n); // __123.4567 (on ne précise que la largeur)aussi appelés caractères de contrôle, ils commencent toujours par le caractère backslash : \
il permettent de faire des actions spécifiques, comme un retour à ligne, une tabulation, ... :
xxxxxxxxxx101\a Bip sonore (BEL)2\b Backspace (BS), revient d'un caractère en arrière3\n Newline (NL), saute au début de la ligne suivante4\r Carriage Return (CR), revient au début de la ligne5\t Horizontal Tab (HT), avance au "taquet" suivant6\\ Backslash (\), affiche un \ (barre inversée)7\' Single Quote ('), affiche un signe ' (apostrophe)8\" Double Quote ("), affiche un signe " (guillemet)9\0 Le caractère NUL (zéro), code ASCII 00010\xnnn Le caractère de code ASCII nnn (hexa), p.ex \x041 affiche 'A'
xxxxxxxxxx11scanf("<chaine de commande>", &<var1>, [...] , &<varN>);exemple :
xxxxxxxxxx21int day, month, year;2scanf("%d/%d/%d", &day, &month, &year);<chaine de commandes>
spécification de format de lecture des variables, p.ex : %d, %f, etc...
%f pour float%lf pour doubledes caractères alphanumériques
<Liste de variables>
& pour envoyer l'adresse des variables)Si on ajoute des caractères alphanumériques comme dans l'exemple précédent (/) il faut le taper pendant la saisie !
il faudrait donc taper par exemple 0 1 / 0 1 / 2 0 0 0 <enter>
scanf renvoie le nombre de champs remplis par l'utilisateur.
fflush(stdin) vide le buffer d'entrée
ifxxxxxxxxxx61if (<condition>)2{3 <instruction1>;4 <instruction2>;5 ...6}ou éventuellement (mais à éviter)
xxxxxxxxxx21if (<condition>)2 <instruction>;La deuxième syntaxe ne fonctionne que pour une seule instruction, sinon, il faut mettre les accolades.
Attention, il n'y a pas de ; après le if, sinon les instructions à l'intérieur du bloc ne s'exécuteront pas!

if elsexxxxxxxxxx81if (<condtition>)2{3 <bloc>4}5else6{7 <bloc>8}ou éventuellement (mais à éviter)
xxxxxxxxxx41if(<condition>)2 <instruction>;3else4 <instruction>;
if et else ne se terminent pas par ;{ et } définissent un bloc d'instructionselse n'existe pas sans ifif peut exister sans elseIl existe plusieurs manière de placer les accolades dans le code. Cela n'influencera pas l'exécution du code mais uniquement sa lisibilité. Il n'y a pas vraiment de meilleure façon de faire, l'important est que le code soit lisible, compréhensible et d'être cohérent dans tout le programme (i.e. ne pas changer et/ou alterner de façon d'écrire)
xxxxxxxxxx71if (x == y) {2 ..3} else if (x > y) {4 ..5} else {6 ..7} xxxxxxxxxx121if (x == y) 2{3 ..4} 5else if (x > y) 6{7 ..8}9else 10{11 ..12} L'opérateur renvoie un résultat en fonction du résultat d'une opération logique.
Syntaxe :
xxxxxxxxxx11result = <condition> ? <valueIfTrue> : <valueIfFalse>;switchswitch seul xxxxxxxxxx151switch(value)2{3 case <val_A>: 4 <instruction_A1>;5 <instruction_A2>;6 ...7
8 case <val_B>: 9 <instruction_B1>;10 <instruction_B2>;11 ...12 13 default:14 <instructions>;15}On va évaluer la valeur de value.
Si value == <val_A> alors on exécute toutes les instructions à partir de <instruction_A1> jusqu'à la fin.
Dès qu'on rencontre une condition vérifiée, on exécute les instructions à partir de cet endroit.

switch + breakAvec le mot clé break on indique que l'on veut quitter le branchement switch. On peut alors uniquement exécuter les instructions qui correspondent à la condition testée et pas les suivantes.
xxxxxxxxxx181switch(value)2{3 case <val_A>: 4 <instruction_A1>;5 <instruction_A2>;6 ...7 break;8
9 case <val_B>: 10 <instruction_B1>;11 <instruction_B2>;12 ...13 break;14 15 default:16 <instructions>;17 break;18}
switch vs if..elseswitch ne permet que de tester des égalités entre valeurs entière ou de type char
switch ne peut pas tester des valeurs réelles, des chaînes de caractères, des structures, des tableaux ou des intervalles de valeurs.
Un if..else peut toujours remplacer un switch mais l'inverse n'est souvent pas possible.
whileTant que la condition est vérifiée, répéter [...]
xxxxxxxxxx41while(<condition>)2{3 <bloc>4}
Avec la boucle while, tant que la condition est vraie, on exécute les instructions du bloc, mais le corps n'est pas forcément exécuté (si la condition est fausse dès le départ)
Il faut faire attention à ce que le corps de la boucle puisse modifier la condition afin de la rendre fausse, sinon on aura affaire à une boucle infinie.
do..whileRépéter [...] tant que la condition est vraie
xxxxxxxxxx51do2{3 <bloc>4}5while(<condition>);
Les instructions du blocs sont exécutées puis répétées tant que la condition est vraie.
Cela signifie que le corps de la boucle est exécuté au moins une fois (étant donné que la condition est testée en fin de boucle)
Attention : L'instruction while du do..while doit se terminer par ;
forRépéter un certain nombre de fois [...]
xxxxxxxxxx41for(<init> ; <condition> ; <incr>)2{3 <bloc>4}
La boucle for permet de répéter une ou plusieurs instructions un certain nombre de fois.
On utilise un indice pour compter le nombre de fois que la boucle est effectuée.
Sa valeur doit :
cette instruction doit initialiser la variable d'indice (exécutée qu'une seule fois, à l'entrée de la boucle)
cette condition doit être vraie pour que les conditions de la boucle s'exécutent
instruction qui incrémente (ou décrémente) la variable d'indice.

(1) l'expression d'
whileLa boucle for
xxxxxxxxxx41for (i=1; i<132; i+=2)2{3 <instructions>;4}est équivalent avec une boucle while à
xxxxxxxxxx61i = 1;2while(i<132)3{4 <instructions>;5 i += 2;6}La boucle for est à privilégier quand on connait à l'avance le nombre d'itérations à effectuer.
Si on ne connait pas à l'avance le nombre d'itérations :
do..while si le corps de la boucle doit être effectué au moins une foiswhile si on ne doit pas forcément entrer dans la bouclereturnL'instruction return termine l'exécution de la fonction courante.
exit(<int>)La fonction exit permet de terminer l'exécution où que l'on se trouve.
Elle prend un paramètre (code d'erreur entier) destiné à l'environnement d'exécution (0=OK, -1=ERR)
une directive #include <stblib.h> est nécessaire.
Cette instruction est utile pour quitter la fonction en cas d'erreur.
il existe également :
breakcontinuegotoA l'exception de l'instruction break utilisée à l'intérieur d'un branchement switch, l'utilisation de ces instructions est à bannir!



xxxxxxxxxx11result = function(<arg1>, <arg2>, ... <argN>);xxxxxxxxxx61<type> function_name(<type> arg1, <type> arg2, ...)2{3 <instructions>;4 5 return <return_value>6}L'en-tête de la fonction doit être connu par le compilateur avant son premier appel. Si la fonction est déclarée après son appel, il est alors nécessaire de définir son prototype avant son premier appel :
xxxxxxxxxx161/* prototype de la fonction */2<type> function_name(<type> arg1, <type> arg2, ...);3
4int main()5{6 /* appel de la fonction */7 function_name(1,2,3,...);8}9
10/* définition de la fonction */11<type> function_name(<type> arg1, <type> arg2, ...)12{13 <instructions>;14 15 return <return_value>16}Si une fonction est définie dans un autre fichier, son prototype doit alors être inclus dans le fichier header (file.h) :
main.c
xxxxxxxxxx712
3int main()4{5 function_name(args);6 return 0;7}file.h
xxxxxxxxxx21/* prototype de la fonction */2<type> function_name(<type> arg1, <type> arg2, ...);file.c
xxxxxxxxxx71/* définition de la fonction */2<type> function_name(<type> arg1, <type> arg2, ...)3{4 <instructions>;5 6 return <return_value>7}On utilise l'instruction return pour renvoyer une valeur.
L'exécution de toute fonction se termine si :
return}exitTypes possibles :
structvoidIl faut toujours indiquer le type du retour.
→ paramètres indiqués dans la définition de la fonction
Fonction sans paramètre formel (void)
xxxxxxxxxx11<type> function_name(void);Fonction avec paramètre formels
xxxxxxxxxx11<type> function_name(int a, double b, float* c, ...);Les paramètre peuvent être de n'importe quel type.
→ paramètres indiqué lors de l'appel de la fonction (arguments)
Les paramètres effectifs doivent être compatible avec les paramètres formels. Cela peut être des expressions, des constantes ou des variables.
xxxxxxxxxx11function_name(a, b+c, f(4));Si la fonction retourne une valeur, elle peut ensuite être utilisée (affectée à une variable ou être utilisée dans une autre expression)
xxxxxxxxxx21int var = function_name(a,b,c); 2int var = sqrt(function_name(a,b,c));Les variables sont visibles dans le bloc où elles ont été déclarées.
ce sont des variables qui sont déclarées en dehors de toute fonction :
Elles sont déclarées dans un bloc (dans le corps d'une fonction)

staticLorsqu'une variable locale est déclarée avec le mot-clé static:
Les variables statiques permettent de gérer la persistance tout en ayant un statut privé.
