From 459cf8a8c8cec64ad0b3cb47b21fa699babf60a3 Mon Sep 17 00:00:00 2001 From: tth Date: Mon, 23 Aug 2021 09:54:19 +0200 Subject: [PATCH] le langage C --- chap/C.tex | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 309 insertions(+), 9 deletions(-) diff --git a/chap/C.tex b/chap/C.tex index f542365..ca289aa 100644 --- a/chap/C.tex +++ b/chap/C.tex @@ -1,10 +1,16 @@ -\chapter{Langage C} +\chapter{Le langage C} \label{C}\index{C} Un chapitre un peu particulier, puisque c'est le début d'une initiation au langage C pour les non-codeurs qui souhaitent rentrer dans le sujet à la dure. +Certaines des explications qui vont suivre ne sont pas très +rigoureuses, mais montrent bien les principes généraux et +les erreurs classiques. La futilité des exemples est assumée. + +Les détails nécessaires seront présentés dans la suite. + % --------------------------------------------------------- \section{Hello World} @@ -15,10 +21,14 @@ Le tout début d'un programme en C est l'appel par le \textsl{runtime} d'une fonction nommée \texttt{main} qui reçoit deux paramètres dont l'utilisation est décrite un peu plus bas. +Ces paramètres sont fournis par le système d'exploitation. \lstinputlisting[language=c]{code/hello.c} - +Un fois passé l'entrée, nous somme dans la partie active. +Nous appelons à ce moment la fonction \texttt{printf} +qui a pour but d'afficher sur l'écran le texte +passé en paramètre. Voila, c'est fait. Nous savons dire bonjour au monde. Point suivant~: dire boujour à quelqu'un d'autre. Et pour @@ -30,27 +40,317 @@ de commande. \section{Arguments} Expliquons maintenant les deux paramètres -\texttt{argc} et \texttt{argv}. - +\texttt{argc} et \texttt{argv} du point d'entrée du programme +(la fonction main). Le premier est le nombre de "mots" détectés par l'interpréteur de commande qui va lancer votre proggy, et le second est -un tableau contenant ces différents mots. +un tableau de chaines de caractères contenant ces différents mots. + +Ce petit bout de code va nous afficher tout ça~: \lstinputlisting[language=c]{code/arguments.c} +Et voici un exemple d'exécution depuis un shell~:\index{shell} + \begin{verbatim} $ ./arguments un deux "trois quatre" - 0 ./arguments. - 1 un. - 2 deux. - 3 trois quatre. + 0 ./arguments + 1 un + 2 deux + 3 trois quatre $ \end{verbatim} +Nous constatons que la première valeur affichée est en fait +le nom de notre programme, ou plutôt le chemin vers le fichier +exécutable, et surtout que son indice est 0, ce qui semble +logique\footnote{Rez-de-chaussée, premier étage, toussa\dots}. +En C, les tableaux commencent toujours à l'indice 0. + +Pour le traitement des options, il faut sauter à +la page \pageref{getopt}. + +% --------------------------------------------------------- +\section{Les variables} + +En gros, une variable du C est une zone de mémoire destinée +à contenir une valeur. +Une variable peut être caractérisée par trois choses~: +son nom, son type, et sa portée. + +\textbf{Le nom} : Il doit commencer par une +lettre\footnote{To be ASCII or not to be ?} majuscule ou minuscule, +laquelle peut être suivie d'un nombre suffisant de lettres, de chiffres +et du caractère 'souligné'. La différence de casse est signifiante. + +\textbf{Le type} : C'est une désignation du genre d'information +que l'on peut stocker dans une variable. + +\textbf{La portée} : + +% --------------------------------------------------------- +\section{Les fonctions} + +Nous avons vu brièvement dans la première section de ce chapitre +la fonction \texttt{main} et ses deux paramètres. +Il est temps de préciser les détails. % --------------------------------------------------------- +\section{Entrées / Sorties} +\index{stdin} \index{stdout} \index{stderr} + +\subsection{Les trois flux canoniques} + +\texttt{stdin}, \texttt{stdout} et \texttt{stderr}\dots + +Par défaut, au lancement du programme, ces trois canaux +d'entrée/sortie sont pré-connectés, et donc directement +utilisables. +Le premier (\texttt{stdin}), l'entrée standard, est connecté +au clavier du consoliste\footnote{De quel roman est tiré ce terme ?}, +le second (\texttt{stdout}), la sortie standard, permet d'afficher +les résultats du programme sur l'écran, +et le troisème (), la sortie d'erreur, permet d'afficher +les éventuels messages d'erreur. +La différence entre \textsl{out} et \textsl{err} est expliquée +plus loin. + +\subsection{IO de base}\index{getchar}\index{putchar} + +Les fonctions \texttt{getchar} et \texttt{putchar} sont les plus +simples. +Avec elles, on peut lire un caractère depuis \texttt{stdin}, +et afficher un caractère dans \texttt{stdout}. Tout cela semble +très bien, mais la fonction de lecture est piégeuse +"\textsc{It's a trap}", comme nous allons bientôt le voir. + + +\subsection{Écrire : \texttt{printf}} +\index{printf} + +La fonction \texttt{printf} permet d'afficher le contenu d'une +(ou plusieurs) +variable sous divers formats contrôlables par un petit DSL. + +\begin{verbatim} +int bar, foo = 42; +bar = printf ("foo = %d\n", foo); +\end{verbatim} + +La première ligne déclare deux variables dont une (foo) est +initialisée à une valeur connue. La seconde ligne appelle +la fonction '\texttt{printf}' avec les paramêtres appropriés et +conserve la valeur de retour de celle-ci. + +Le premier de ces paramêtres, \texttt{"foo = \%d\textbackslash{}n"}, +est appelé \emph{chaine de format}. C'est une chaine de caractères +que l'on peut classer en trois catégories~: + +\textsl{caractères crus} : ils sont directements poussés vers la sortie. + +\textsl{codes de format} : les fragments qui commencent par le +caractère '\%'. + +\textsl{échappements} : les caratères précédés d'un +'\textbackslash'. +\subsection{Lire : \texttt{scanf}} +\index{scanf} +Avez-vous bien révisé la section qui cause des pointeurs ? + +% --------------------------------------------------------- + +\section{Un filtre Unix}\label{filtre-unix} + +Ce qu'on appelle un "filtre" est un logiciel destiné à transformer +les données qui le traversent. Pour bien comprendre, le mieux, +comme d'habitude, est un exemple. Il est un peu artificiel, +il s'agit d'éliminer les lettres \textsc{o} et \textsc{p}. +Le voici~: + +\lstinputlisting[language=c]{code/no-op.c} + +Démonstration~: + +\begin{verbatim} +$ echo apopoz | ./no-op +az +$ ./no-op < no-op.c | head -5 +/* + * n-.c is an useless shell filter + */ +#include +#include +$ +\end{verbatim} + +Pour une explication plus détaillée sur les mécanismes +utilisés et les usages possibles, +il faut voir le concept de pipeline en +page \pageref{pipeline}. + +% --------------------------------------------------------- + +\section{Les pointeurs}\label{pointeur}\index{pointeur} + +\textbf{Ah, enfin, on a failli attendre !} + +Qu'est-ce qu'un pointeur ? La réponse est multiple, et c'est +le pointeur qui fait à la fois la force et la faiblesse du C. +Pour faire simple, un pointeur est une variable qui contient +l'adresse dans la mémoire d'une autre variable. + +% --------------------------------------------------------- + +\section{Le préprocesseur}\index{cpp} + +Nous avons déja abordé de loin la directive \texttt{\#include}, +qui fait partie du préprocesseur, comme toutes les lignes +de code commençant par le caractère \textbf{\#}. +Le concept de base, qu'il faut bien capter, est que le +préprocesseur pratique des \emph{substitutions de texte}. +Pratiquement, il se passe ça~: + +\begin{verbatim} +#define NUMID 1664 +#define FLAVOUR "tisane" +printf("La %d c'est de la %s\n", NUMID, FLAVOUR); +\end{verbatim} + +Ces trois lignes de code +(deux directives pour cpp et un appel classique de fonction) +seront converties en une seule ligne de C. + +\begin{verbatim} +printf("La %d c'est de la %s\n", 1664, "tisane"); +\end{verbatim} + +C'est donc cette ligne qui sera ensuite passée au vrai compilateur +pour être traduite en codes opératoires, dont l'exécution +affichera une maxime dont la véracité demande à être vérifiée +par l'expérimentation. Mais ça n'est pas fini. + +Ce sympathique \textsf{préproc'} nous permet aussi de faire +de la compilation conditinnelle, et ça, c'est cool parce que +ça ouvre la porte à plein de choses. +Par exemple, l'instrumentation du code afin de faciliter +les tests et le debug. + +\begin{verbatim} +... +#ifdef TRACEUR +fprintf(stderr, "pid %d was here.\n", getpid()); +#endif +... +\end{verbatim} + +Et à la compilation, il vous faut passer l'option +\texttt{-DTRACEUR} à Gcc pour que ce message de trace soit +pris en compte. + +% --------------------------------------------------------- + +\section{Unités de compilation} + +Jusque à maintenant, nous n'avons vu que des programmes dont +le code source n'était que dans un seul fichier, ce qui devient +vite ingérable pour un gros projet. C permet facilement +de faire de la compilation séparée~: chacun des fichiers source +est compilé indépendament en un fichier \textsl{objet}, lesquels +seront ensuite \textbf{liés} pour obtenir l'exécutable final. + +Mais découper un gros logiciel en plusieurs fichiers source +a d'autres avantages. + +% --------------------------------------------------------- + +\section{Les structures} + +Une structure est une sorte de boite dans laquelle on peut +ranger plusieurs variables afin de les manipuler comme +une seule entité. + +% --------------------------------------------------------- + +\section{Gestion de la mémoire} +\index{malloc} \index{free} + +Nous avons déja entrevu la gestion « implicite » de la mémoire +avec les variables locales. Il est temps de passer à une gestion +explicite de celle-ci~: +les fonctions \texttt{malloc} et \texttt{free} sont là pour ça. + +La première demande au mc/p de nous préter une certaine quantité +de mémoire, que nous pourront utiliser à notre guise. +Et la seconde restitue la zone mémoire au système sous-jacent. + +Un rapide synopsis minimal d'utilisation~: + +\begin{verbatim} +int foo, *ptr; +if (NULL==(ptr=malloc(sizeof(int)*NBITEMS))) abort(); +for (foo=0; foo +int getopt(int argc, char * const argv[], const char *optstring); +extern char *optarg; +extern int optind, opterr, optopt; +\end{verbatim} + +La page de man de getopt(3) contient des explications détaillées +et un exemple simple d'utilisation. + + +% ========================================================= + +\section{Ailleurs dans cet ouvrage} + +Il y a plein d'autres exemples de code en C, sur des sujets +divers comme Open Sound Control (page \pageref{chap:OSC}) ou +libsndfile (page \pageref{chap:son}). +Et pour les gens du système~: +l'utilisation des signaux (page \pageref{get-signal}). + + +% ---------------------------------------------------------