L'adresse de ``global`` ne change pas, car elle fait partie du segment texte du programme. Les autres sont soit sur la pile (stack), ou sur le tas (heap).
L'adresse de ``global`` ne change pas, car elle fait partie du segment texte du programme. Les autres sont soit sur la pile (stack), ou sur le tas (heap).
#. Un étudiant a fait l'implémentation d'un sous-ensemble des fonctions définies dans string.h, mais il rencontre quelques problèmes avec son code :download:`/Programmes/src/string.c`. Utilisez `gdb <http://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_ pour corriger son code. Utilisez le flag ``-g`` de ``gcc`` pour ajouter les informations de debug dans votre executable. Pour rappel, voici quelques commandes importantes de `gdb <http://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_:
#. Un étudiant a fait l'implémentation d'un sous-ensemble des fonctions définies dans string.h, mais il rencontre quelques problèmes avec son code :download:`/Programmes/src/string.c`. Utilisez `gdb <http://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_ pour corriger son code. Utilisez le flag ``-g`` de ``gcc`` pour ajouter les informations de debug dans votre executable. Pour rappel, voici quelques commandes importantes de `gdb <http://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_:
- ``run [ARGS]`` permet de lancer l'execution du programme avec les arguments ARGS si spécifiés.
- ``run [ARGS]`` permet de lancer l'execution du programme avec les arguments ARGS si spécifiés.
- ``break string.c:9`` met un point d'arrêt à la ligne 9 du fichier string.c
- ``break string.c:9`` met un point d'arrêt à la ligne 9 du fichier string.c
- ``next`` permet d'executer la ligne courante et de s'arrêter à la ligne suivante
- ``next`` permet d'executer la ligne courante et de s'arrêter à la ligne suivante
- ``print var`` affiche la valeur de la variable ``var``
- ``print var`` affiche la valeur de la variable ``var``
- ``backtrace`` affiche la pile d'appel des fonctions courantes
- ``backtrace`` affiche la pile d'appel des fonctions courantes
4 erreurs: strlen ne check pas NULL, strlen appelé à chaque itération de strcat, argc pas vérifié, concat_2 pas initialisé
4 erreurs: strlen ne check pas NULL, strlen appelé à chaque itération de strcat, argc pas vérifié, concat_2 pas initialisé
#. Vous travaillez sur un programme qui doit manipuler des vecteurs. Afin de pouvoir supporter des vecteurs de taille quelconque, vous décidez de réimplémenter ces vecteurs vous même en utilisant des pointeurs. Votre programme définit la structure ``struct vector_t`` et les fonctions ci-dessous.
#. Vous travaillez sur un programme qui doit manipuler des vecteurs. Afin de pouvoir supporter des vecteurs de taille quelconque, vous décidez de réimplémenter ces vecteurs vous même en utilisant des pointeurs. Votre programme définit la structure ``struct vector_t`` et les fonctions ci-dessous.
Implémentez ces fonctions sans jamais utiliser la notation des tableaux en C (``[`` et ``]``).
Implémentez ces fonctions sans jamais utiliser la notation des tableaux en C (``[`` et ``]``).
.. literalinclude:: /Programmes/src/vector.c
:encoding: utf-8
:language: c
:start-after: ///AAA
:end-before: ///BBB
.. only:: staff
.. literalinclude:: /Programmes/src/vector.c
:encoding: utf-8
:language: c
:start-after: ///AAA
:end-before: ///BBB
#. Faites l'exercice relatif aux `linked lists <https://inginious.info.ucl.ac.be/course/LSINF1252/linked_lists_1>`_ sur INGInious.
.. only:: staff
.. only:: staff
#. Expliquez la différence entre `malloc(3)`_ et `calloc(3)`_. D'après vous, quel appel sera le plus lent ?
#. Faites l'exercice relatif aux `linked lists <https://inginious.info.ucl.ac.be/course/LSINF1252/linked_lists_1>`_ sur INGInious.
.. only:: staff
#. Dans la fonction ``push`` du programme de manipulation d'un pile :download:`/../Theorie/C/S3-src/stack.c`, faut-il remplacer l'appel à `malloc(3)`_ par un appel à `calloc(3)`_
.. only:: staff
.. note::
#. Expliquez la différence entre `malloc(3)`_ et `calloc(3)`_. D'après vous, quel appel sera le plus lent ?
Non. La zone mémoire est initialisée directement après.
.. only:: staff
.. only:: staff
#. Dans la fonction ``push`` du programme de manipulation d'un pile :download:`/../Theorie/C/S3-src/stack.c`, faut-il remplacer l'appel à `malloc(3)`_ par un appel à `calloc(3)`_
#. Le prototype de la fonction ``push`` du programme de manipulation d'une pile :download:`/../Theorie/C/S3-src/stack.c`, est ``void push(struct fraction_t *)``. Serait-il possible d'écrire une function push ayant comme prototype ``void push(struct fraction_t)`` ? Qu'est-ce qui changerait dans ce cas ?
.. note::
.. note::
Non. La zone mémoire est initialisée directement après.
Pas possible.
.. only:: staff
.. only:: staff
#. Le prototype de la fonction ``push`` du programme de manipulation d'une pile :download:`/../Theorie/C/S3-src/stack.c`, est ``void push(struct fraction_t *)``. Serait-il possible d'écrire une function push ayant comme prototype ``void push(struct fraction_t)`` ? Qu'est-ce qui changerait dans ce cas ?
#. Les fonctions ``push`` et ``pop`` définies dans l'exemple de manipulation d'une pile :download:`/../Theorie/C/S3-src/stack.c` utilisent une pile qui est définie par un pointeur qui est une variable globale. Est-il possible de réécrire ces fonctions de façon à ce qu'elles prennent comme argument un pointeur vers la pile ? Leurs prototypes deviendraient :
Oui, idéalement dans ce cas, il faudrait définir une fonction init qui renverrait un ``struct node_t *``.
#. Les fonctions ``push`` et ``pop`` définies dans l'exemple de manipulation d'une pile :download:`/../Theorie/C/S3-src/stack.c` utilisent une pile qui est définie par un pointeur qui est une variable globale. Est-il possible de réécrire ces fonctions de façon à ce qu'elles prennent comme argument un pointeur vers la pile ? Leurs prototypes deviendraient :
Oui, idéalement dans ce cas, il faudrait définir une fonction init qui renverrait un ``struct node_t *``.
typedef struct {
.. only:: staff
char c;
long l;
short s;
} test_t;
Combien de bytes seront utilisés en mémoire pour représenter cette structure? Représentez graphiquement la position en mémoire de chaque élément (utilisez `printf(3)`_ et ``%p``), observez-vous des trous ? Expliquez.
#. Considérons la structure suivante:
Serait-il possible d'utiliser moins de bytes pour représenter cette structure ? Si oui, comment ?
.. note::
.. code-block:: c
La structure prend 16 bytes d'espace (sur une machine 64-bits - 12 bytes sur une machine 32 bits). C'est dû au fait que les champs sont alignés à des multiples de 64 bits (resp. 32 bits) pour éviter d'avoir des parties de variables copié sur plusieurs registres. Pour optimiser, il suffit de reordonner les champs. Par exemple:
typedef struct {
char c;
long l;
short s;
} test_t;
.. code-block:: c
typedef struct {
Combien de bytes seront utilisés en mémoire pour représenter cette structure? Représentez graphiquement la position en mémoire de chaque élément (utilisez `printf(3)`_ et ``%p``), observez-vous des trous ? Expliquez.
char c;
Serait-il possible d'utiliser moins de bytes pour représenter cette structure ? Si oui, comment ?
short s;
long l;
} test_t;
.. only:: staff
.. note::
.. note::
La structure prend 16 bytes d'espace (sur une machine 64-bits - 12 bytes sur une machine 32 bits). C'est dû au fait que les champs sont alignés à des multiples de 64 bits (resp. 32 bits) pour éviter d'avoir des parties de variables copié sur plusieurs registres. Pour optimiser, il suffit de reordonner les champs. Par exemple:
Elle bypasse l'alignement décrit dans la question précédente. L'avantage est que la structure prend l'espace minimale n'importe soit l'ordonnancement des champs. Le désavatage est que la CPU doît faire plus de travail pour lire la variable, car des parties de la variable sont sur plusieurs registres, et donc la CPU doît faire des bit-shifts.
.. code-block:: c
typedef struct {
char c;
short s;
long l;
} test_t;
.. only:: staff
.. note::
Elle bypasse l'alignement décrit dans la question précédente. L'avantage est que la structure prend l'espace minimale n'importe soit l'ordonnancement des champs. Le désavatage est que la CPU doît faire plus de travail pour lire la variable, car des parties de la variable sont sur plusieurs registres, et donc la CPU doît faire des bit-shifts.
#. Expliquez à quoi sert l'attribut ``packed`` des structures dans `gcc(1)`_ (regardez la manpage). Appliquez cet attribut à la structure de l'exercice précédent. Qu'observez-vous comme différence ? Quel sont les avantages et désavantages d'utiliser cet attribut ? Dans quel cas est-il intéressant de l'utiliser ?
#. Expliquez à quoi sert l'attribut ``packed`` des structures dans `gcc(1)`_ (regardez la manpage). Appliquez cet attribut à la structure de l'exercice précédent. Qu'observez-vous comme différence ? Quel sont les avantages et désavantages d'utiliser cet attribut ? Dans quel cas est-il intéressant de l'utiliser ?
.. only:: staff
.. note::
.. note::
Il bypasse l'alignement décrit dans la question précédente. L'avantage est que la structure prend l'espace minimal n'importe soit l'ordonnancement des champs. Le désavantage est que la CPU doît faire plus de travail pour lire la variable, car des parties de la variable sont sur plusieurs registres, et donc la CPU doît faire des bit-shifts.
Il bypasse l'alignement décrit dans la question précédente. L'avantage est que la structure prend l'espace minimal n'importe soit l'ordonnancement des champs. Le désavantage est que la CPU doît faire plus de travail pour lire la variable, car des parties de la variable sont sur plusieurs registres, et donc la CPU doît faire des bit-shifts.
#. Exécutez plusieurs fois le code suivant. Expliquez les différents résultats obtenus.
.. only:: staff
.. code-block:: c
int global;
#. Exécutez plusieurs fois le code suivant. Expliquez les différents résultats obtenus.