Aller au contenu

DS 4 (MP2I 2022-2023) — C et mémoire

Devoir surveillé · MP2I · 2022-2023 · partie I du DS 4 (2 h 30 au total)

Cours : Gestion de la mémoire

Autres parties : II. Placement des convives

Tout document interdit. Tout dispositif électronique interdit.

On vous demande d'écrire lisiblement et de bien présenter. Les programmes en particulier doivent être bien indentés et lisibles.

C et mémoire

On considèrera dans ce sujet que tous les en-têtes ont déjà été inclus en C.

Question 1

Expliquer brièvement l'organisation de la mémoire d'un programme compilé.

On tachera de faire un diagramme indiquant les différentes zones mémoire ainsi que leur rôle.

Corrigé

Voir cours.

Question 2

Si i est une valeur du type int et que p et q sont des pointeurs du type int *, indiquez les instructions d'affectation licites :

a) p = i;    b) *p = &i;    c) &p = q;

d) p = &q;    e) p = *&q;    f) p = q;

g) p = *i;    h) *p = q;    i) *p = *q;

Corrigé

Les instructions e, f et i sont licites.

Pour s'en convaincre, on pouvait faire un tableau en indiquant les types à gauche et à droite du symbole = :

gauche droite
a int * = int
b int = int *
c int ** = int *
d int * = int **
e int * = int *
f int * = int *
g int * = invalide
h int = int *
i int = int

Question 3

  • Écrire une fonction de prototype

    void max_min(int a[], int n, int *min, int *max);
    

    qui prend en entrée un tableau t de n entiers, supposé non vide, et place la plus petite valeur dans min passé par pointeur, et sa plus grande valeur dans max.

  • Écrire une fonction main typique qui testerait cette fonction sur le tableau {1, 5, -1, 3} en affichant la réponse sous la forme

    min=-1 max=5
    
Corrigé
void max_min(int a[], int n, int *min, int *max)
{
    *min = a[0];
    *max = a[0];
    for (int i = 1; i < n; i++)
    {
        if (*min > a[i])
            *min = a[i];
        if (*max < a[i])
            *max = a[i];
    }
}
int main(void) {
    int t[] = { 1, 5, -1, 3 };
    int max, min;
    max_min(t, 4, &min, &max);
    printf("min=%d max=%d\n", min, max);
}

Question 4

Écrire une fonction de prototype

void find_two_largest(int a[], int n,
    int *largest, int *second_largest);

qui prend en entrée un tableau t de n entiers, en supposant \(n > 1\), et place la plus grande valeur présente dans largest et la seconde plus grande dans second_largest.

Exemple : pour { 1, 4, 5, 2, 4 } on va donc avoir 5 dans largest et 4 dans second_largest.

Corrigé

Un classique des fausses questions faciles. Il y a deux pièges :

  • on ne peut pas initialiser aux deux premières valeurs parce qu'elles peuvent être égales. Il faut donc chercher les deux premières valeurs différentes.
  • il faut bien faire attention à ne pas faire deux if successifs dans la boucle car le premier if perturbe le second.
void find_two_largest(int a[], int n,
    int *largest, int *second_largest)
{
    *largest = a[0];
    int i = 1;
    while (a[i] == *largest)
        i++;
    if (a[i] > *largest) {
        *second_largest = *largest;
        *largest = a[i];
    } else {
        *second_largest = a[i];
    }
    for (int j = i + 1; j < n; j++) {
        if (a[j] > *largest) {
            *second_largest = *largest;
            *largest = a[j];
        } else if (a[j] < *largest && a[j] > *second_largest)
            *second_largest = a[j];
    }
}

On suppose ici que le tableau contient au moins deux valeurs distinctes, sinon la boucle while sort du tableau.

Question 5

On considère les structures suivantes :

struct point {
    int x;
    int y;
};
struct rectangle {
    struct point upper_left;
    struct point lower_right;
};

Écrire une fonction de prototype

rectangle *mon_rectangle();

qui alloue et renvoie un rectangle de coin supérieur gauche de coordonnées \((10, 25)\) et de coin inférieur bas \((20, 15)\).

Corrigé

Faute de typedef, il faut écrire struct rectangle (ou ajouter typedef struct rectangle rectangle;).

struct rectangle *mon_rectangle() {
    struct rectangle *r = malloc(sizeof(struct rectangle));
    r->upper_left.x = 10;
    r->upper_left.y = 25;
    r->lower_right.x = 20;
    r->lower_right.y = 15;
    return r;
}

Question 6

Écrire une fonction de prototype

int *create_array(int n, int initial_value);

qui alloue un tableau de \(n\) entiers et initialise chaque case avec la valeur initial_value.

Corrigé
int *create_array(int n, int initial_value)
{
    int *t = malloc(n * sizeof(int));
    for (int i = 0; i < n; i++)
        t[i] = initial_value;
    return t;
}