C : bases

De Justine's wiki
Aller à la navigation Aller à la recherche


Livre de référence

Ici en pdf

J'ai décidé de réapprendre le C. Et comme j'avais appris toutes mes bases de Python en suivant les cours open classrooms, je vais faire pareil ici avec leur cours "Apprenez à programmer en C".

Outils

Je vais utiliser les outils habituels :

  • make ou clang pour la compilation
  • gdb comme debugger (si je comprends comment il fonctionne)
  • vim comme éditeur de texte.

Je ne rentrerais pas dans code::blocks ou autres.

BoilerPlate : includes, fonction main, syntaxe

Le langage a besoin d'un minimum de code, que voici présenté dans un hello world:

<source>

  1. include <stdio.h>
  2. include <stdlib.h>

int main(int argc, char *argv[]) { printf("Hello world !\n"); return 0; } </source>

Que signifie tout ça ?

  • Les includes (qui sont elles-mêmes des directives de préprocesseur, car elles seront lues par le... préprocesseur): permettent d'inclure des librairies. Ici, on inclut stdio (Standard Input Output Header) qui est la librairie gérant les opérations d'entrée / sortie entre le processeur et les autres composants (RAM, ROM, etc). Stdlib est la librairie standard, qui inclut divers utilitaires très courants.
  • int main etc: En C, on utilise une fonction principale (comme en python en fait, ou elle est implicite).

Fonctions (base)

Une fonction en C se décortique comme suit :

return_type nom(paramètres) accolade
  • return type : le type de variable que va renvoyer ma fonction
  • nom : son p'tit nom
  • paramètres : ce qu'elle va prendre en entrée.
  • accolade : la fonction est définie entre accolades.
  • le corps de la fonction, qui fait des trucs.
  • return : le retour de la fonction. Soit ça renvoie quelque chose comme un nombre, un str... soit ça peut renvoyer 0 pour dire que tout va bien. Pas de return(True) ici !

Exemple de fonction plus simple qu'un main: <source>

<source> /* function returning the max between two numbers */ int max(int num1, int num2) {

  /* local variable declaration */
  int result;

  if (num1 > num2)
     result = num1;
  else
     result = num2;

  return result; 

} </source>

Alors, que signifie les paramètres d'une fonction main ? Si on se rappelle que le main() correspond au programme en lui-même, tel que lancé dans mon shell, on comprend vite :

  • int argc : un main prend d'abord le nombre d'arguments envoyés au programme. Il est au moins de 1, car il y'a le programme en lui-même.
  • char *argv[] : C'est un tableau de str, qui contiendra les paramètres en eux-mêmes.

Compiler avec clang

Une compilation simple de notre helloworld.c n'est pas compliquée : <source> clang hello.c

  1. Nous donne un a.out, qui est le programme compilé

</source>

Syntaxe

Point-virgules ?

Les points-virgules signifient que l'instruction en cours est terminée. Les retours à la ligne ne sont pas pris en compte (les tabs non plus), et on peut d'ailleurs coder comme des sagouins sur une seule ligne: <source>

  1. include <stdio.h>
  2. include <stdlib.h>

int main(int argc, char *argv[]) { printf("Hello !\n"); return 0; } </source> ...mais bon, code propre, tout ça :3

Les commentaires s'écrivent avec // pour une ligne, ou entre /* */ sur plusieurs lignes: <source> // Mon beau commentaire /* Mon commentaire entre balises */ </source>

Variables

En C, les noms de variables ont des contraintes : que des lettres, des chiffres, des underscores. On ne peut pas nommer ses variables avec des emojis :(

https://openclassrooms.com/fr/courses/19980-apprenez-a-programmer-en-c/7669586-declarez-des-variables

Asterisques et pointeurs

Source

L’astérisque est généralement associé, en C, aux pointeurs (et à la multiplication, aussi). Par exemple, lorsque l'on déclare un pointeur: <source lang="c"> // i est un entier int i = 5; // p est un pointeur vers un entier, initialisé à NULL int *p = NULL; // &i correspond à l'adresse de i, qu'on assigne à p p = &i; /* Quand il ne s'agit pas d'une déclaration, * sert à déréférencer un pointeur.

* Ici, p pointe sur i; donc, i vaudra désormais 123 */
  • p = 123;

/* Et d'ailleurs, quand on veut changer l'adresse sur laquelle un pointeur pointe, on

* a pas besoin d'astérisque. */

p = &une_autre_variable; </source>

Par déréférencer, dans "*p = 123;", il s'agit de dire "cette assignation ne va pas directement sur toi, p, mais sur la variable vers laquelle tu pointes".

On peut d'ailleurs déclarer et initialiser un pointeur en même temps :

int *p = &i;

Mais une subtilité à comprendre :

  • "int i = 5" et "int i; i = 5" sont bien similaires;
  • Mais "int *p = &i;" et "int *p; *p = &i;" ne donnent pas la même chose. En effet, le second va essayer de déréférencer un pointeur pas initialisé (j'ai pas compris).

Tableaux de caractères

Quelle est la différence entre "char i[10]" et "char *i" ? https://wiki.squi.fr/index.php/Fichier:Arraycharr.jpg Ce n'est pas clair... Je l'accorde volontiers.