Questions à choix multiples¶
La matière couverte cette semaine la section relative aux types de données (jusque et y compris la section relative aux expressions de manipulation de bits
Question 1. Conversion de types¶
En C tout comme dans des langages comme Java, il est possible de convertir des nombres d’un type primitif vers un autre. Cependant, alors que le compilateur Java vérifie si la conversion est sans risque, le compilateur C ne fait aucune vérification et suppose que si le programmeur a effectué une conversion explicite entre types, il a pris ses précautions. Sur une architecture où les types de données sont stockés comme suit :
// char 1 octet(s)
// unsigned char 1 octet(s)
// short 2 octet(s)
// unsigned short 2 octet(s)
// int 4 octet(s)
// unsigned int 4 octet(s)
int i;
short s;
long l;
char c;
unsigned int ui;
unsigned char uc;
unsigned long ul;
unsigned short us;
i=(int ) s;
s=(short) uc;
l=(long )i;
ui=(unsigned int) us;
s=(short) c;
ul=(unsigned long )ui;
ui=(unsigned int ) s;
us=(unsigned short) uc;
l=(long )i;
i=(int ) us;
us=(unsigned short) i;
l=(long )c;
ui=(int) s;
s=(short) c;
ul=(unsigned long )ui;
Question 2. Notation hexadécimale¶
27
est 1B
67
est 43
La représentation hexadécimale du nombre entier positif 67
est 34
La représentation hexadécimale du nombre entier positif 27
est B1
La représentation hexadécimale du nombre entier positif 62
est B1
La représentation hexadécimale du nombre entier positif 128
est FF
Question 3. Notation binaire¶
99
est 1100011
176
est 10110000
La représentation binaire du nombre entier positif 90
est 1100011
La représentation binaire du nombre entier positif 176
est 10110001
La représentation binaire du nombre entier positif 166
est 10110001
La représentation binaire d’un nombre entier positif impair a toujours 0
comme bit de poids faible.
Question 4. Notation binaire¶
x
est un short
(signé) sur 16 bits, alors la représentation binaire de -17
est 11111111 11101111
x
est un short
(signé) sur 16 bits, alors la représentation binaire de -23
est 11111111 11101001
Si la variable x
est un short
(signé) sur 16 bits, alors la représentation binaire de -17
est 00000000 00010001
Si la variable x
est un short
(signé) sur 16 bits, alors la représentation binaire de -17
est 10000000 00010001
Si la variable x
est un short
(signé) sur 16 bits, alors la représentation binaire de -23
est 00000000 00010111
Si la variable x
est un short
(signé) sur 16 bits, alors la représentation binaire de -23
est 11111111 11100110
Question 5. Manipulations de bits¶
c
est de type unsigned char
sur 8 bits, laquelle des suites d’instructions ci-dessous permet d’en échanger les 4 bits de poids faible avec les 4 bits de poids fort ?unsigned char temp1, temp2;
temp1 = c & 0x0F;
temp2 = c & 0xF0;
temp1=temp1 << 4;
temp2=temp2 >> 4;
c= temp2|temp1;
unsigned char temp1, temp2;
temp1=c << 4;
temp2=c >> 4;
c= temp2|temp1;
unsigned char temp1, temp2;
temp1=c << 4;
temp2=c >> 4;
c= temp2||temp1;
unsigned char temp1, temp2;
temp1=4 << temp1;
temp2=4 >> temp2;
c= temp2|temp1;
unsigned char temp1, temp2;
temp1 = c && 0x0F;
temp2 = c && 0xF0;
temp1=temp1 << 4;
temp2=temp2 >> 4;
c= temp2|temp1;
Question 6. Multiplication entière¶
x*7
lorsque x
est un nombre entier. Laquelle ?(x<<3)-x
(x>>3)-x
(x<<3)+x
(x<<7)
(x>>7)
Question 7. Extraction de bits¶
Il est parfois nécessaire en C de manipuler directement la représentation binaire d’un nombre. Si f
est un nombre de type float
stocké sur 32 bits, laquelle des expressions ci-dessous peut-elle être intégrée dans ce code pour afficher positif ou négatif en fonction du signe de ce nombre ?
if(<à compléter>)
printf("positif\n");
else
printf("negatif\n");
!(((unsigned int) f) & 0x80000000)
!(((unsigned int) f) >> 31)
!(((unsigned int) f) & 0x10000000)
!(((unsigned int) f) << 31)
!(((unsigned int) f) > 31)
!(((unsigned int) f) & 31)
Question 8. Chaînes de caractères¶
c
dans la chaîne de caractères c
. Laquelle ?int count1(char *s, char c) {
int i=0;
int count=0;
while(*(s+i)!='\0') {
if(*(s+i)==c) {
count++;
}
i++;
}
return(count);
}
int count(char *s, char c) {
int count=0;
while(*(s)!='\0') {
if(*(s)==c) {
count++;
}
s++;
}
return(count);
}
int count1(char *s, char c) {
int i=0;
int count=0;
while(i<s.length) {
if(*(s+i)==c) {
count++;
}
i++;
}
return(count);
}
int count1(char *s, char c) {
int i=0;
int count=0;
while(*s!=`\0`) {
if(*(s+i)==c) {
count++;
}
i++;
}
return(count);
}
int count(char *s, char c) {
int count=0;
while(*(s)!='\0') {
s++;
if(*(s)==c) {
count++;
}
}
return(count);
}
int count(char *s, char c) {
int count=0;
while(s!='\0') {
if(s==c) {
count++;
}
s++;
}
return(count);
}
Question 9. Pointeurs¶
ptr
a été déclaré sous la forme int *ptr
, un seul des groupes d’affirmations suivantes est vrai, lequel ?- l’expression
*(ptr + 1)
est une valeur entière - l’expression
ptr[1]
est une valeur entière - l’expression
ptr
est une adresse en mémoire
- l’expression
*(ptr) + 1
est une valeur entière - l’expression
ptr[2]
est une valeur entière - l’expression
ptr++
est une adresse en mémoire
- l’expression
&(ptr) + 1
est un nombre entier - l’expression
ptr[2]
est une valeur entière - l’expression
&ptr
est une adresse en mémoire
- l’expression
*(ptr+1)==ptr[1]
est syntaxiquement invalide - l’expression
ptr[2]
est une valeur entière - l’expression
&ptr
est une adresse en mémoire
- l’expression
*(ptr+1)==ptr[1]
est toujours vraie - l’expression
ptr--
est syntaxiquement invalide
Question 10. Pointeurs et tableaux¶
Considérons le tableau tab
déclaré comme suit :
#define SIZE 30 int tab[SIZE]; int *ptr;
- l’expression
tab[i]
correspond à la même valeur dans le tableau que*(tab+i)
lorsque0<=i<29
- l’assignation
ptr=(tab+i)
est valide et après cette assignation,*ptr
retourne la même valeur quetab[i]
lorsque0<=i<29
- l’expression
tab[0]
correspond à la même valeur dans le tableau que*(tab)
- l’assignation
ptr=(tab+i)
est valide et après cette assignation,*ptr
retourne la même valeur quetab[i]
lorsque0<=i<29
- l’expression
tab[i]
correspond à la même valeur dans le tableau que*(tab+i)
lorsque0<=i<29
- l’assignation
tab=(tab+i)
est valide et après cette assignation,*tab
retourne le ième élément du tableau lorsque0<=i<29
- l’expression
tab[0]
correspond à la même valeur dans le tableau que&(tab)
- l’assignation
tab=(tab+i)
est valide et après cette assignation,*tab
retourne le ième élément du tableau lorsque0<=i<29
- l’expression
tab[i]
correspond à la même valeur dans le tableau que*(tab)+i
lorsque0<=i<29
- l’assignation
ptr=(tab)
est valide et après cette assignation,*(ptr+i)
retourne le ième élément du tableau lorsque0<=i<29
Question 11. Pointeurs¶
Considérons le fragment de code ci-dessous.
int tab[]={ 10, 20, 30, 40 };
int *ptr1=&tab[1];
int *ptr2=&tab[3];
ptr2-ptr1
vaut 2
*(ptr1-1)
et *(ptr2-3)
retournent toutes les deux la même valeur, 10
l’expression ptr2-ptr1
vaut 20
les expressions *(ptr1-1)
et *(ptr2-3)
retournent toutes les deux la même valeur, 1
l’expression *(ptr2-ptr1)
retourne la valeur 20
Question 12. Pointeurs et fonctions¶
a
et b
sont des variables de type int
, laquelle des fonctions ci-dessous permet de réaliser cette échange entre les contenu des variables ?void swap(int *i, int *j) {
int k;
k=*i;
*i=*j;
*j=k;
}
//échange
swap(&a,&b);
void swap(int *i, int *j) {
int k;
k=*j;
*j=*i;
*i=k;
}
//échange
swap(&a,&b);
void swap(int i, int j) {
int k;
k=i;
i=j;
j=k;
}
//échange
swap(a,b);
void swap(int i, int j) {
int k;
k=i;
i=j;
}
//échange
swap(&a,&b);
void swap(int i, int j) {
int k;
int *i_ptr=&i;
int *j_ptr=&j;
k=i;
*(i_ptr)=j;
*(j_ptr)=k;
}
//échange
swap(a,b);
Question 13. Pointeurs et structures¶
Dans un programme de manipulation de fractions, on définit la structure suivante pour représenter une fraction entière :
struct fract_t { int num; int denum; };
On veut pouvoir facilement écrire une fonction de type void
qui remplace la valeur stockée dans la fraction par le résultat de l’addition de la fraction et un nombre entier passé en fragment. La spécification de cette fonction pourrait être :
/* * augmente la fraction passé en argument de l'entier n et place * la somme calculée dans la fraction * Exemples * Si f vaut 1/3, alors l'application de la fonction avec f et 2 comme * arguments a comme résultat de stocker la valeur 7/3 dans f * Si f vaut 2/1, alors l'application de la fonction avec f et 1 comme * arguments a comme résultat de stocker la valeur 3/1 dans f */
void scale(struct *fract_t f, int s);
// appel à la fonction :
// scale(&f,3);
void scale(struct fract_t f, int s);
// appel à la fonction :
// scale(f,3);
void scale(int num, int den, int s);
// appel à la fonction :
// scale(f.num, f.denum,3);
s
est négatif, la conversion enunsigned int
risque de poser problème.