2 - Types et variables

CHAPITRE 2 : types et variables #

Cours #

Squelette Ă  remplir #

#include <stdio.h>

// CHAPTER 2

int main(void)
{
	// Experiment with identifiers.


	// Check size in bytes of most common types.
	// Example: printf("char          : %zu bits\n", 8 * sizeof(char));


	// Experiment with assignements


	// Experiment with blocks and variables


	// Write swap instructions


	// Declare constants with const keyword and #define preprocessor directives
	

	return 0;
}

📝 À NOTER

%zu est le spécificateur de format pour des valeurs de type size_t.

Quiz #

QUIZ TYPES ET VARIABLES (~15’)

EXERCICES #

Exercice 1 #

Parmi les noms de variables suivants, indiquer ceux qui sont corrects :

nombre		Auto			Dollar$			Ligne4
17h20		ARC_EN_CIEL	RouGE7			vert/jaune
"poisson"	Pourcent		descriptiondinterface1
n			ZoRRo			arbre()			Lumière!

Exercice 2 #

Vérifier si les déclarations de variables ci-dessous sont conformes aux règles du C.

{
  int a, b=2, c;
  float 4roues, Deux_Roues, tricycle;
  double PIBSuisse_;
  real  PIB_USA_en_$;
  char c;
}

Si ce n’est pas le cas, dire pourquoi.

Exercice 3 #

Écrire la définition des variables pour un programme qui utilise les valeurs suivantes :

  • la valeur de \(\pi\)
  • un numĂ©ro de tĂ©lĂ©phone Ă  10 chiffres
  • le sexe d’une personne (Homme / Femme)
  • le taux de change de l’Euro en francs suisse
  • le numĂ©ro du mois actuel (4 pour avril, 5 pour mai, …)
  • l’initiale de votre premier prĂ©nom
  • la valeur boursière de la sociĂ©tĂ© Apple (>150'000'000'000 de $)

Justifier les choix faits.

Exercice 4 #

Écrire la définition des variables pour le programme suivants :

#include <stdio.h>

int main(void)
{
  // Definitions

  // Instructions
  pi = 3.14; // Not needed if we use const double pi = 3.14
  birthYear = 1963;
  month = 10;
  day = 10;
  letter = 'b';

  return 0 ;
}

Exercice 5 #

Représenter les nombres binaires suivants en notation décimale et hexadécimale.

\(01010001_{2} = \)  

\(00011110_{2} = \)

\(00111100_{2} = \)  

\(01111000_{2} = \)  

Exercice 6 #

Représenter les nombres décimaux suivants en notation binaire et hexadécimale.

\(33_{10} = \)  

\(255_{10} = \)  

\(101_{10} = \)  

Exercice 7 #

En représentation binaire, comment savoir si un nombre est pair ou impair ?

Exercice 8 #

Combien de valeurs peut-on dénombrer avec des mots de 8, 16, 32 et 64 bits ?

Exercice 9 #

Soient 3 octets arrivant sur un bus de 8 bits, quel est leur code ascii associé et quel est le mot formé ? (exercice avec calculatrice et table ascii)

\(00111010_{2} = \)  

\(00101101_{2} = \)  

\(00101001_{2} = \)  

Exercice 10 #

Soient 3 nombres hexadécimaux, quel est leur code ascii associé et quel est le mot formé ? (avec calculatrice)

\(31_{16}\)  

\(32_{16}\)  

\(32_{16}\)  

Exercice 11 #

Compléter le programme suivant pour qu’il échange le contenu des variables \(variable1\) et \(variable2\) .

#include <stdio.h>

int main(void)
{
  int variable1 = 10;
  int variable2 = 5;

  // Before swapping the variables content
  printf("Variable 1: %d \n", variable1); // Variable 1: 10
  printf("Variable 2: %d \n", variable2); // Variable 2: 5

  // Swap variables content

  ...

  // After swapping the variables content
  printf("Variable 1: %d \n", variable1); // Variable 1: 5
  printf("Variable 2: %d \n", variable2); // Variable 2: 10
}

🧠 NOTION AVANCÉE

Exercice 12 #

Écrire le code permettant d’échanger les valeurs contenues dans les deux variables a et b sans utiliser d’autre variable.

🧠 NOTION AVANCÉE

Exercice 13 #

Quelle est la valeur du nombre de type float dans la variable chouia dont le contenu mémoire est représenté ci-dessous ?

float chouia    /* = ??? */    ;

Exercice 21 #

Écrire un programme C qui convertit une température saisie par l’utilisateur en degrés Celsius, en degrés Fahrenheit et l’affiche :

Enter a temperature in Celsius: 12
12 degres Celsius correspond to a 53.6 degres Fahrenheit

Indication : \( T_F = 32 + 1.8*T_C \)

Exercice 22 #

Écrire un programme C qui effectue un calcul d’intĂ©rĂŞts et de capital pour un compte en banque. Il demande Ă  l’utilisateur d’introduire:

  • Le capital initial sur le compte (francs et centimes)
  • Le taux d’intĂ©rĂŞt (annuel) du compte en pourcent
  • La durĂ©e du dĂ©pĂ´t (on ne peut retirer l’argent qu’au terme d’une annĂ©e complète) puis il calculera le montant disponible lors du retrait et l’affichera en francs et centimes selon la formule \(asset = initAmount * (1 + rate)^{duration}\)
What is your initial asset? 1000
What is your yearly interest rate (in pourcent)?: 2.5
Duration in years? 30

After 30 years, your assets (with interest) will be     2097.57 SFr

🧠 NOTION AVANCÉE

Exercice 23 #

AmĂ©liorer l’affichage pour avoir des sĂ©parateurs après les milliers, et millions, et arrondir le montant Ă  5 centimes. La valeur 1876435.264901 affichera par exemple 1'876'435.30 SFr

🧠 NOTION AVANCÉE

Exercice 24 #

Implémenter le codage d’un nombre réel donné par l’utilisateur, en virgule flottante selon IEEE754

  • Calcul du bit signe (facile)
  • Calcul de l’exposant (moyen)
  • Calcul de la mantisse (difficile?)
  • VĂ©rification avec les bits du nombre mĂ©morisĂ© dans une variable float (difficile)

Défis #

Comparaison de flottants #

Qu’affiche le programme suivant ? Pourquoi ? Quelle est la bonne manière de comparer des double ?

#include <stdio.h>

int main(void)
{
  double d1 = 0.3;
  double d2 = 0.1 + 0.1 + 0.1;
  if (d1 == d2)
  {
    printf("d1 is equal to d2\n");
  }
  else
  {
    printf("d1 is NOT equal to d2\n");
  }
  

  return 0;
}
Explications

Le programme affiche d1 is NOT equal to d2. En effet, en reprĂ©sentation binaire, 0.1 est une valeur pĂ©riodique (comme 1/3 en dĂ©cimal). Donc, 0.1 ne peut pas ĂŞtre reprĂ©sentĂ©e exactement en binaire. Par consĂ©quent, la somme de 3 fois 0.1 n’est pas exactement Ă©gale Ă  0.3. La bonne manière de comparer des double est de vĂ©rifier que la diffĂ©rence entre les deux valeurs est infĂ©rieure Ă  une petite valeur epsilon (typiquement la plus petite valeur reprĂ©sentable par un double : DBL_EPSILON).

#include <stdio.h>
#include <math.h>
#include <float.h>

int main(void)
{
  double d1 = 0.3;
  double d2 = 0.1 + 0.1 + 0.1;
  if (d1 == d2)
  {
    printf("d1 is equal to d2\n");
  }
  else
  {
    printf("d1 is NOT equal to d2\n");
  }

  if (fabs(d1 - d2) < DBL_EPSILON)
  {
    printf("d1 is approximately equal to d2\n");
  }
  else
  {
    printf("d1 is NOT approximately equal to d2\n");
  }

  return 0;
}

Cast de double en char #

Qu’affiche le programme suivant ? Pourquoi ?

#include <stdio.h>

int main(void)
{
	// Cast 128 into a char (8 bits) => overflow
	printf("c1 = %d\n", (char)128);
	char c1 = 128;
	printf("c1 = %d\n", c1);

	// 1)
	double d2 = 128.99;
	char c2 = (char) d2;
	printf("d2 = %lf\n", d2);
	printf("c2 = %d\n", (char) c2);

	// 2)
	double d3 = (char) 128.99;
	char c3 = (char) d3;
	printf("d3 = %lf\n", d3);
	printf("c3 = %d\n", (char) c3);
	printf("c3 = %d\n", (char) 128.99);

	return 0;
}
Explications

Le code cast un double (128.99) en char. Comme la valeur maximale reprĂ©sentable par un char est 127, il devrait y avoir dĂ©bordement (overflow). On s’attend donc Ă  avoir -128 au final.

Cependant, le programme affiche :

c1 = -128
c1 = -128
d2 = 128.990000
c2 = -128
d3 = 127.000000
c3 = 127
c3 = 127

La norme dit :

6.3.1.4 Real floating and integer

When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.

Donc, quand un double est castĂ© en char, seule la partie entière est conservĂ©e. Si elle ne peut pas ĂŞtre reprĂ©sentĂ©e dans le type entier demandĂ© (ici char), alors c’est un comportement indĂ©fini.

Dans l’exemple de code donnĂ©, les parties 1) et 2) sont donc des comportements indĂ©finis. Et le compilateur (ici GCC) va faire les choses diffĂ©remment.

Dans le cas 1), comme la valeur est stockĂ©e dans une variable, le cast se fera Ă  l’exĂ©cution. Il prend donc la valeur stockĂ©e dans la variable (128.99), ne garde que la partie entière (128), et la cast en char. Si char est signĂ© (plage [-128,127]), 128 n’est pas reprĂ©sentable : la conversion a un comportement indĂ©fini. Dans ce cas particulier, l’exĂ©cution affiche -128, mais elle pourrait tout aussi bien afficher 0, 127, 42, ou provoquer un crash. Si char est non signĂ© (plage [0,255]), la conversion est bien dĂ©finie et donne 128.

Dans le cas 2), le compilateur voit directement que la partie entière de la constante 128.99 ne pourra pas ĂŞtre reprĂ©sentĂ©e sur un char et prend des mesures, donc directement durant la compilation. En particulier, il dĂ©cide d’utiliser la valeur maximale reprĂ©sentable par un char, et donc on rĂ©cupère 127.

👉 Ne jamais se fier au résultat d’un cast hors bornes. En C, c’est un comportement indéfini.

LAST MODIFIED
November 03, 2025
Benoit Le Callennec
9077778

© HE-Arc 2020-2025 - Tous droits rĂ©servĂ©s.