Le langage C

C'est le langage d'origine associé à Unix. Il permet de la programmation scientifique classique, ou de la programmation système via les librairies associées.

Outils associés

Le langage C est un langage compilé. Il y a:

Compiler, c'est:

Depuis un source a.c:

Les options du compilateur sont: Exemple:
	# en un coup
	gcc -o myprog myprog.c
	# en 2 coups
	gcc -c myprog
	gcc -o myprog myprog.o
	# avec la librairie math en dynamique
	gcc -o myprog myprog.c -lm
	# avec la librairie math en statique
	gcc -o myprog myprog.c -Bstatic -lm

La compilation séparée

Un gros programme peut être découpé en fichiers indépendants.
Exemple:
Soit un fichier principal, une première partie, une seconde partie. La compilation sera:
gcc -c main.c
gcc -c part1.c
gcc -c part2.c
gcc -o main main.o part1.o part2.o
qui donne à l'exécution:
Ceci est un message 1
Ceci est le fichier part1, message de part2()
Ceci est un message 1
Pour information:
$ size main
text    data    bss     dec     hex
8192    8192    0       16384   4000

Le langage C

Syntaxe

Le format est libre. Néanmoins il y a un format standard, par exemple la sortie de cb(1).
Les commentaires sont /* commentaire */.
Les identificateurs sont une lettre, suivi de lettres ou chiffres ou de soulignés. Il y a des mots réservés.

Constantes

Types de données

avec la variante: NB: la notion de booléen n'existe pas, on peut remplacer par un char.

En Ansi C, il existe aussi le type enum:

enum couleur { violet = 0, indigo, bleu, vert, jaune, orange,
	      rouge};

Constructeurs

Les pointeurs
Un pointeur est l'adresse mémoire d'un élément. Exemple:
	int *a, b;
	a = &b;		/* b contient l'adresse de a */
	*a = 5;		/* ce qui est pointé par a reçoit 5 */
Cas particulier: le pointeur NULL.
Les tableaux
Indicé toujours à partir de 0.
Exemples:
	float f[20][10];
	int c[] = {30, 20, 10, 5,};
	unsigned char hello[] = "Hello, World!\n";
Dans le dernier exemple:
	hello[0] = 'H';
	hello[1] = 'e';
	...
	hello[13] = '\n';
	hello[14] = '\0';
Il y a définition implicite de pointeurs.
Les structures
On met en mémoire à la suite les différents champs:
	struct complex {
		float re, im;
	};
	struct chaine {
		char *c;
		struct chaine *next;
	};
	struct string {
		char s[80];
		struct string *next;
	};
Les unions
On met en parallèle en mémoire les différents champs.
	union entier {
		char c[4];
		int n;
	};
Les champs de bit
C'est une structure où l'on descend au niveau du bit.
	struct word {
		unsigned octet:8;
		unsigned fill:7;
		unsigned bit:1;
		unsigned demi:16;
	};
Les typedef
Permet un raccourci.
	typedef struct { float re, im; } complex;

Allocation en mémoire, portée

Ici un exemple compliqué.

NB: on obtient la table des symboles via nm(1).

Les affectations

var = expression
lue aussi lvalue = expression
Le tableau des opérateurs par priorité décroissante:
-	a[b]	a(b,c,d)	a.b		a->b
-	a++		++a		&expr	*expr	+expr	-expr	~expr	!expr
-	sizeof(type)
-	(type)expr
-	*		%		/
-	+		-
-	<<		>>
-	<=		>=		<		>
-	==		!=
-	&
-	^ 
-       |
-	&&
-	||
-	a ? b : c
-	a=b		a+=b		a-=b
-	expr, expr
Quelques remarques:

Les instructions

Les fonctions

Tout en C est une fonction. Le type void permet de faire des fonctions sans paramètre ou sans résultat (donc identique à une procédure). Une fonction ressemble en ANSI C à:
TYPE_RESULTAT fct(type1 var1, type2 var2) {
	...
	return RESULTAT;
}
ou en C classique:
TYPE_RESULTAT fct(var1, var2)
type1 var1;
type2 var2;
{
	...
	return RESULTAT;
}
Le type de résultat ne peut pas être un tableau; ce doit être un type simple, (en ANSI C) une structure ou une union. Un cas particulier: tout programme exécutable est une fonction main:
int main(int argc, char **argv, char **envp);
{
	return...;
	/* ou : exit ...	*/
}
Le résultat de main, i.e. l'argument de exit ou du return de la procédure main est le code de retour du programme.
Tous les arguments sont passés par valeurs. Quelques déclarations possibles:
	extern int max(int,int);
	void swap(&int,&int);
	char *lirechaine(void);
	int count();
	int *f();	/* f est une fonction rendant un pointeur vers
				un entier */
	int (*f)();	/* f est un pointeur vers une fonction a
				resultat entier */

La fonction printf

Le premier argument est un format:
	%d		%08d		%x		%-3d
	%c
	%s		%-20s		%10s
	%f		%8.2f		%e		%g
	%%
qui dit comment seront imprimés les arguments suivants.
Exemples:
	printf("Ceci est un texte\n");
	printf("i = %d, j = %d\n",i,j);
	printf("%20s\n","Ceci est court!");

Variante: sprintf
Un premier argument s'ajoute: une chaîne où sera écrit le résultat:
	char line[80];
	sprintf(line,"i = %d j = %f\n",i,j);
Ces fonctions rendent:
- en Berkeley: 0 ou EOF
- en System V : le nombre de caractères ou EOF.

La fonction scanf

Sachant que toute variable est passée par valeur, il faut donner à scanf des pointeurs! Le principe est identique à printf:
	scanf("%d %d",&i,&j);
	scanf("i = %d",&i);
Cette fonction rend le nombre d'arguments effectivement lus.
Variante sscanf()
Même principe que sprintf(). Application: reconnaissance de lignes:
	gets(line);
	if (sscanf("i = %d,&i) == 1) {
		....;
	}
	if (sscanf("x = %f",&x) == 1) {
		....;
	}

Le préprocesseur

Il a plusieurs fonctions:

En librairie

Quelques programmes