Questions à choix multiples¶
Question 1. Portée des variables¶
Lorsque l’on écrit un programme C, il est préférable d’éviter d’avoir deux variables qui ont le même nom et peuvent être utilisées dans une fonction. Un étudiant a écrit le programme ci-dessous :
#include <stdio.h> int i = 1; int main(int argc, char * argv[]) { int k; printf("A:%d\n", i); for(k=0; k<1; k++) { int i = 2, j = 1252; printf("B:%d %d\n", i, j); { int i = 0; printf("C:%d %d\n", i, j); } printf("D:%d\n", i); } return 0; }
A:1
B:2 1252
C:0 1252
D:2
Le programme ne se compile pas, il est interdit de redéfinir la variable globale i.
A:1
B:1 1252
C:1 1252
D:1
A:1
B:2 1252
C:2 1252
D:2
A:1
B:2 1252
C:0 1252
D:0
Question 2. Portée des variables¶
L’extrait ci-dessous provient d’un programme écrit par un étudiant.
#include <stdio.h> int i = 1252; void f(int i) { // code non fourni } void g(char* c) { // code non fourni } int main(int argc, char * argv[]) { f(argc); g(argv[0]); }
- La fonction
gpeut accéder à la variable globaleiet modifier sa valeur - La fonction
gne peut lire la valeur deargc - La fonction
fne peut modifier la valeur de la variable globalei
- La fonction
gpeut lire la variable globaleimais pas modifier sa valeur - La fonction
gne peut lire la valeur deargc - La fonction
fpeut modifier la valeur de la variable globalei
- La fonction
fpeut lire la variable globaleimais pas modifier sa valeur - La fonction
gpeut lire la valeur deargc - La fonction
fpeut modifier la valeur de la variable globalei
- La fonction
fpeut lire la variable globaleiet modifier sa valeur - La fonction
gne peut lire la valeur deargc - La fonction
fne peut modifier la valeur de la variable globalei
Question 3. Organisation de la mémoire¶
Considérons le fragment de programme ci-dessous.
#include <stdio.h> int i,j,k = 1252; // ligne A int tab[1000]; // ligne B void f(int i) { // ligne C int j; // ligne D // code non fourni } void g(char c) { int i; // ligne E // code non fourni } int main(int argc, char * argv[]) { int k=1; // ligne F f(argc); g('a'); }
- la variable
idéclarée enligne Aest stockée dans la zone des variables non-initialisées - l’argument
idéclaré enligne Cest stocké sur la pile - la variable
jdéclarée enligne Dest stockée sur la pile - la variable
kdéclarée enligne Fest stockée sur la pile
- la variable
idéclarée enligne Aest stockée dans la zone des variables non-initialisées - le tableau
tabdéclaré enligne Best stocké dans la zone des variables non-initialisées - l’argument
idéclaré enligne Cest stocké sur la pile - la variable
idéclarée enligne Eest stockée sur la pile
- le tableau
tabdéclaré enligne Best stocké dans la zone des variables initialisées - l’argument
idéclaré enligne Cest stocké sur la pile - la variable
jdéclarée enligne Dest stockée sur la pile - la variable
idéclarée enligne Eest stockée sur la pile - la variable
kdéclarée enligne Fest stockée dans la zone des variables non-initialisées
- le tableau
tabdéclaré enligne Best stocké dans la zone des variables non-initialisées - l’argument
idéclaré enligne Cest stocké sur le tas - la variable
kdéclarée enligne Fest stockée sur la pile
- le tableau
tabdéclaré enligne Best stocké dans la zone des variables non-initialisées - l’argument
idéclaré enligne Cest stocké sur la pile - la variable
jdéclarée enligne Dest stockée sur la pile - la variable
idéclarée enligne Eest stockée sur le tas - la variable
kdéclarée enligne Fest stockée sur la pile
- la variable
idéclarée et initialisée enligne Aest stockée dans la zone des variables initialisées - le tableau
tabdéclaré enligne Best stocké dans la zone des variables non-initialisées - l’argument
idéclaré enligne Cest stocké sur la pile - la variable
kdéclarée enligne Fest stockée sur le tas
Question 4. Initialisation des variables¶
En C, une règle de bonne pratique est d’initialiser toutes les variables avant leur utilisation. Utiliser une variable qui n’a pas été correctement initialisée peut être une source de problèmes. Un étudiant a écrit les déclarations ci-dessous :
int k=0; int i; short j; float f=0.0; double d; char c[10]; char* string; void* v; int* ptr; ptr=(int*) malloc(5*sizeof(int));
- la variable
kest initialisée à la valeur0 - la variable
fest initialisé à la valeur0 - la variable
ptrest stockée sur la pile - Après exécution de
malloc, le contenu de l’adresseptr+1est indéterminé
- la variable
dcontient une valeur indéterminée - le pointeur
vcontient une valeur indéterminée c[9]va faire un accès mémoire sur la pile- Après une exécution réussie de
malloc, le contenu deptrest une adresse sur le tas
- la variable
fest initialisée à la valeur0.0 - le pointeur
stringn’est pas utilisable c[2]contient le caractère espace- Après exécution de
malloc, l’adresseptr+1contient le caractère'\0'
- la variable
fest initialisée à la valeur0.0 - le pointeur
vn’a aucune valeur et n’est pas utilisable c[2]contient le caractère'\0'- Après exécution de
malloc, l’adresseptrcontient le caractère'\0'
- la variable
fest initialisée à la valeur0.0 - la variable
jcontient une valeur indéterminée - le pointeur
stringcontient une valeur indéterminée - Après une exécution réussie de
malloc, le contenu deptrest une adresse sur la pile
- la variable
fest initialisée à la valeur0.0 - la variable
icontient une valeur indéterminée - la variable
dcontient une valeur indéterminée - Après exécution de
malloc, l’adresseptr+5contient le caractère'\0'
Question 5. malloc(3) et compagnie¶
Cette question porte sur les fonctions malloc(3) et free(3) qui sont importantes pour la manipulation de la mémoire sur le tas.
la fonction malloc(3) retourne un pointeur de type
void *la fonction free(3) prend comme argument un pointeur de type
void *qui a été précédemment alloué par la fonction malloc(3)si l’appel à calloc(3) a retourné un pointeur différent de
NULL, alors la zone mémoire demandée a été allouée et est initialisée à zéroune implémentation possible (non efficace) de realloc(3) est
void *realloc(void *ptr, size_t len) { void *r; r = malloc(len); if(r!=NULL) { memcpy(r, ptr, len); free(ptr); } return r; }
la fonction malloc(3) retourne un pointeur de type
void *la fonction free(3) prend comme argument n’importe quel type de pointeur
si l’appel à malloc(3) a retourné un pointeur différent de
NULL, alors la zone mémoire demandée a été allouée mais n’est pas initialisée à zéroune implémentation possible (non efficace) de realloc(3) est
void *realloc(void *ptr, size_t len) { void *r; r = malloc(len); memcpy(r, ptr, len); return r; }
la fonction calloc(3) retourne un pointeur de type
void *la fonction free(3) prend comme argument un pointeur de type
void *qui a été précédemment alloué par la fonction malloc(3)si l’appel à malloc(3) a retourné un pointeur différent de
NULL, alors la zone mémoire demandée a été allouée et est initialiséeune implémentation possible (non efficace) de realloc(3) est
void *realloc(void *ptr, size_t len) { return malloc(len); }
la fonction calloc(3) retourne un pointeur de type
void *la fonction free(3) prend comme argument un pointeur de type
void *qui a été précédemment alloué par la fonction malloc(3)si l’appel à malloc(3) a retourné un pointeur différent de
NULL, alors la zone mémoire demandée a été allouée et est initialiséeune implémentation possible (non efficace) de realloc(3) est
void *realloc(void *ptr, size_t len) { void *r; r = malloc(len); if(r) { return r; } else { return NULL; } }
Question 6. Stack¶
size permettant de calculer le nombre d’éléments stockés dans la pile ?int size(struct node_t* stack)
{
struct node_t *curr = stack;
int count = 0;
while (curr!=NULL) {
count ++;
curr = stack->next;
}
return count;
}
int size(struct node_t* stack)
{
int count = 0;
while (stack!=NULL) {
count ++;
stack = stack->next;
}
return count;
}
int size(struct node_t* stack)
{
int count = 0;
while (stack!=NULL) {
count ++;
stack++;
}
return count;
}
int size(struct node_t* stack)
{
return sizeof(stack);
}
int size(struct node_t* stack)
{
struct node_t *curr = stack;
int count = 0;
while (curr) {
count ++;
curr++;
}
return count;
}
int size(struct node_t stack)
{
struct node_t curr = stack;
int count = 0;
while (curr) {
count ++;
curr = stack->next;
}
return count;
}
Question 7. strdup(3)¶
char *strdup(const char *s)
{
char *new = (char *) malloc ((strlen(s)+1) * sizeof(char));
if (new == NULL)
return NULL;
return memcpy(new, s, (strlen(s)+1) * sizeof(char));
}
char *strdup(const char *s)
{
char *new = (char *) malloc ((strlen(s)+1) * sizeof(char));
if (!new)
return NULL;
return memcpy(new, s, (strlen(s)+1) * sizeof(char));
}
char *strdup(const char s)
{
void *new = malloc (strlen(s));
if (new == NULL)
return NULL;
return memcpy(new, s, strlen(s));
}
char *strdup(const char *s)
{
char new [strlen(s)+1];
return memcpy(new, s, (strlen(s)+1) * sizeof(char));
}
char *strdup(const char * s)
{
void *new = malloc (strlen(s+1));
return memcpy(new, s, strlen(s+1));
}
char *strdup(const char *s)
{
char *new = (char *) calloc (strlen(s) * sizeof(char));
if (new == NULL)
return NULL;
return memcpy(new, s, (strlen(s) * sizeof(char)));
}
char *strdup(const char *s)
{
char *new = (char *) malloc (strlen(s) * sizeof(char));
return memcpy(new, s, (strlen(s) * sizeof(char));
}