Bonjour à tous,
Je cherche à visualiser la manière dont sont stockés en mémoire certains types.
En fait je m'interessais surtout aux floats mais comme je rencontrais des difficultés, je me suis rabattu sur le type int. C'est plus facile pour moi de contrôler la justesse de ce que j'observe.
Je travaille avec une vieille machine 32-bit sous Debian stable Jessie et le compilateur GCC livré avec la Debian stable est en version 4.9.2.
Dans un 1er temps voilà ce que j'ai fait :
Ca compile, certes avec 1 message de warning concernant la ligne "p_uc=&n" car p_uc est un pointeur vers un unsigned char et n est int.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 /* dump-int1.c * to compile: gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wstrict-prototypes -Wuninitialized -Wunreachable-code -o dump-int1 dump-int1.c * * It works fine but I don't like the presentation. * The leading byte is at the left (inside the lower memory address) and * the trailing byte is at the right (inside the higher memory address). * It's the opposite the way one writes numbers on the paper. */ #include <stdio.h> #include <limits.h> #include <string.h> #include <stdlib.h> void usage(int rc) { puts("dump-int version 1"); puts("usage: dump-int1 <signed integer>"); printf("with <signed integer> belonging to [%d , %d]\n", INT_MIN, INT_MAX); exit(rc); } int main(int argc, char *argv[]) { int n; unsigned int i; unsigned char *p_uc; if (argc != 2) usage(1); if (strcmp(argv[1], "-h") == 0) usage(0); if ( (n=atoi(argv[1])) == 0 ) usage(1); printf("%d\n", n); /* to check that the conversion with atoi is ok */ p_uc = &n; printf("%02x", *p_uc); for (i=1; i < sizeof(int); i++) { p_uc++; printf(" %02x", *p_uc); } puts(""); return 0; }
Mais ça marche. J'ai fait plusieurs vérification, tout est OK. Les nombres négatifs sont bien des compléments à 2 de leurs homologues positifs.
La seul chose qui m'embête c'est que les octets de poids forts sont à gauche et ceux de poids faible à droite. C'est l'inverse de la manière naturelle pour écrire un nombre.
Je me suis dit qu'à cela ne tienne, je vais changer l'ordre. Mais là, j'ai rencontrés plein de difficulté.
Après moult essais, je me suis aperçu que je pouvais rajouter ou soustraire 1 à un pointeur mais pas 3.
Mon nouveau programme :
Ca compile:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 /* dump-int2.c * to compile: gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wstrict-prototypes -Wuninitialized -Wunreachable-code -o dump-int2 dump-int2.c * * What I do not understand: I can't add more than 1 to a pointer. * p_uc=&n + 3; doesn't work * instead, I have to do: p_uc=&n; p_uc++; p_uc++; p_uc++; */ #include <stdio.h> #include <limits.h> #include <string.h> #include <stdlib.h> void usage(int rc) { puts("dump-int version 1"); puts("usage: dump-int1 <signed integer>"); printf("with <signed integer> belonging to [%d , %d]\n", INT_MIN, INT_MAX); exit(rc); } int main(int argc, char *argv[]) { int n; unsigned int i; unsigned char *p_uc; if (argc != 2) usage(1); if (strcmp(argv[1], "-h") == 0) usage(0); if ( (n=atoi(argv[1])) == 0 ) usage(1); printf("%d\n", n); /* to check that the conversion with atoi is ok */ /* * memory dump view: lower memory adress and the trailing byte are at the * left * higher memory address and leading byte are at the right */ p_uc = &n; printf("memory view: %02x", *p_uc); for (i=1; i < sizeof(int); i++) { p_uc++; printf(" %02x", *p_uc); } puts(""); /* * Natural view with the leading byte at the left and the trailing byte at * the right. */ /* p_uc=&n + sizeof(int) - 1; */ //It doesn't work !! /* p_uc=&n + 3; */ //It doesn't work either p_uc=&n; p_uc++; p_uc++; p_uc++; /* This way, it works !! */ printf("natural view: %02x", *p_uc); for (i=1; i < sizeof(int); i++) { p_uc--; printf(" %02x", *p_uc); } puts(""); return 0; }
Et ça marche :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 brouillons$ gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wstrict-prototypes -Wuninitialized -Wunreachable-code -o dump-int2 dump-int2.c dump-int2.c: In function main: dump-int2.c:33:10: warning: assignment from incompatible pointer type p_uc = &n; ^ dump-int2.c:45:9: warning: assignment from incompatible pointer type p_uc=&n; p_uc++; p_uc++; p_uc++; /* This way, it works !! */ ^
Tout cela m'amène à 2 questions :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 brouillons$ ./dump-int2 1 1 memory view: 01 00 00 00 natural view: 00 00 00 01 brouillons$ ./dump-int2 -1 -1 memory view: ff ff ff ff natural view: ff ff ff ff brouillons$ ./dump-int2 1024 1024 memory view: 00 04 00 00 natural view: 00 00 04 00 brouillons$ brouillons$ ./dump-int2 2147483647 2147483647 memory view: ff ff ff 7f natural view: 7f ff ff ff brouillons$ ./dump-int2 -2147483648 -2147483648 memory view: 00 00 00 80 natural view: 80 00 00 00 brouillons$
Comment peux t'on expliquer que :
"p_uc=&n; p_uc++; p_uc++; p_uc++;" fonctionne,
alors que "p_uc=&n + sizeof(int) - 1;" ne fonctionne pas ?
Plutôt que de bidouiller dans les pointeurs comme je le fais, n'existe t'il pas une méthode plus élégante ?
Merci de votre attention et au plaisir de vous lire.
Partager