Le langage C

François Trahay

Présentation du module

Objectifs du module:

Modalités:


Contenu du module

Partie Programmation

Partie Système

Evaluation


Déroulement d’une séance

Système de classe inversée. Pour chaque séance :

Attention ! Cela ne fonctionne que si vous travaillez sérieusement avant la séance.

Hypothèse: les étudiants suivant ce cours sont des adultes responsables.


Ressources disponibles

Pour vous aider, vous avez à votre disposition:


C vs. Java

Mon premier programme en C

Fichier *.c

/* hello_world.c */
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  printf("Hello World!\n");
  return EXIT_SUCCESS;
}

Compilation/execution:

$ gcc hello_world.c -o hello_world -Wall -Werror
$ ./hello_world
Hello World!


Déclaration de variable

Pour les types simples, déclaration identique à Java:

int var1;
int var2, var3, var4;
int var5 = 42;

Types disponibles: * pour les entiers: int, short, long, long long * pour les flottants: float, double * pour les caractères: char

Pour les entiers: possibilité de préfixer le type par unsigned. Les variables sont alors non-signées (ie. positives).

La taille d’une variable entière (ie. le nombre de bits/octets) dépend de l’implémentation. Le standard C ne spécifie que la taille minimum. Ainsi, un int doit faire au moins 16 bits, alors que la plupart des implémentations modernes utilisent 32 bits pour les int. Il convient donc de ne pas se reposer sur ces types lorsqu’on a besoin d’un nombre précis de bits/octets.

Pour cela, il est préférable d’utiliser les types fournis par stdint.h: uint8_t (8 bits), uint16_t (16 bits), uint32_t (32 bits), ou uint64_t (64 bits).

Comme en Java, les variables déclarées dans une fonction sont locales à la fonction (elles disparaissent donc dès la sortie de la fonction). Les variables déclarées en dehors d’une fonction sont globales: elles sont accessibles depuis n’importe quelle fonction.


Opérateurs et Expressions

La liste des opérateurs disponibles est à peu près la même qu’en Java:

Mais également:


Opérateurs bit à bit

Possibilité de travailler sur des champs de bits.

/* bits.h */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char** argv) {
  uint32_t v = 1;
  int i;

  /* l'operateur << decale vers la gauche */
  for(i=0; i<32; i++) {
    /* v << i  decale les bits de v de i places vers la gauche
     * c'est equivalent à calculer v*(2^i)
     */
    printf("v<<%d = %u\n", i, v<<i);
  }

  v = 5;
  /* v | 3 effectue un OU logique entre les bits de v et la representation binaire de 3
   * 101 | 11 = 111 (7)
   */
  printf("%u | %u = %u\n", v, 3, v|3);

  /* v & 3 effectue un ET logique entre les bits de v et la representation binaire de 3
   * 101 & 11 = 001 (1)
   */
  printf("%u & %u = %u\n", v, 3, v&3);

  /* v ^ 3 effectue un XOR logique entre les bits de v et la representation binaire de 3
   * 101 ^ 011 = 110 (6)
   */
  printf("%u ^ %u = %u\n", v, 3, v^3);

  /* ~v effectue un NON logique des bits de v
   * ~ 00...00101 = 11..11010 (4294967290)
   */
  printf("~%u = %u\n", v, ~v);

  return EXIT_SUCCESS;
}

Remarque

Lorsqu’on opère un décalage (avec <<) sur une valeur signée (par exemple, un int), le bit de signe n’est pas modifié par le décalage. Par exemple, si les bits d’un int a sont à 1010 0000 0000 0000 0000 0000 0000 0000, le résultat de a >> 1 est 1001 0000 0000 0000 0000 0000 0000 0000.


Structures algorithmiques

Comme en Java:


Affichage / Lecture

/* formats.c */
#include <stdio.h>

int main(int argc, char** argv) {
  int v;
  printf("Entrez la valeur de v:\n");
  scanf("%d", &v);
  printf("v = %d (en decimal)\n", v);
  printf("v = %u (en decimal non signe)\n", v);
  printf("v = %x (en hexadecimal)\n", v);
  printf("v = %o (en octal)\n", v);
  printf("v = %c (en ASCII)\n", v);

  double a;
  scanf("%lf", &a);
  printf("a = %f (en flottant)\n", a);
  printf("a = %lf (en flottant double precision)\n", a);
  printf("a = %e (en notation scientifique)\n", a);

  char *chaine = "Bonjour";
  printf("chaine = %s\n", chaine);
  printf("chaine = %p (adresse)\n", chaine);

  printf("On peut aussi afficher le caractère %%\n");
}

Fonctions

Déclaration:

type_retour nom_fonc(type_param1 param1, type_param2 param2) {
/* déclaration des variables locales */
/* instructions à exécuter */
}

En C, il est d’usage de nommer les fonctions en minuscule, en séparant les mots par _. Par exemple, l’équivalent en C de la fonction Java calculerLeMinimum() sera calculer_le_minimum().