2017-08-12 7 views
-1

Quelle sera la sortie du code C suivant. En supposant qu'il fonctionne sur Little machine boutiste, où court int prend 2 octets et char prend 1 octet.Sortie du code C suivant

#include<stdio.h> 
int main() { 
    short int c[5]; 
    int i = 0; 
    for(i = 0; i < 5; i++) 
     c[i] = 400 + i; 
    char *b = (char *)c; 
    printf("%d", *(b+8)); 
    return 0; 
} 

Dans ma machine, il a donné

-108 

Je ne sais pas si ma machine est peu endian ou big endian. J'ai trouvé quelque part qu'il devrait donner

148 

comme sortie. Parce que les 8 bits de poids faible de 404 (c.-à-d. Élément c [4]) sont 148. Mais je pense qu'en raison de "% d", il devrait lire 2 octets de la mémoire à partir de l'adresse de c [4].

+1

L'indicateur de compilation peut changer le caractère par défaut en signe/non signé, etc. –

Répondre

1

c[4] magasins 404. Dans une représentation little-endian de deux octets, cela signifie deux octets de 0x940x01, ou (en décimal) 1481.

b+8 adresse la mémoire de c[4]. b est un pointeur vers char, donc le 8 signifie ajouter 8 octets (ce qui représente 4 courts-circuits de deux octets). En d'autres termes, b+8 pointe sur le premier octet de c[4], qui contient 148.

*(b+8) (qui pourrait aussi être écrit b[8]) déréférence le pointeur et donc vous donne la valeur 148 comme char. Qu'est-ce que cela fait est implémenté-défini: Sur de nombreuses plates-formes communes char est un type signé (avec une plage de -128 .. 127), de sorte qu'il ne peut pas réellement être 148. Mais s'il s'agit d'un type non signé (avec une plage de 0 .. 255), alors 148 est correct. Le modèle de bits pour 148 en binaire est 10010100. Interpréter cela comme un numéro de complément à deux vous donne -108.

Cette valeur char (soit 148 ou -108) est ensuite automatiquement converti en int car il apparaît dans la liste des arguments d'une fonction variable argument (printf). Cela ne change pas la valeur.

Enfin, "%d" indique printf pour prendre l'argument int et le formater en tant que nombre décimal.

Donc, pour récapituler: En supposant que vous avez une machine où

  • un octet est 8 bits
  • nombres négatifs utilisent le complément à deux
  • short int est 2 octets

... alors ce programme produira soit -108 (si char est un type signé) ou 148 (si char est un u type nsigned).

1

Pour voir quelles tailles types ont dans votre système:

printf("char = %u\n", sizeof(char));  
printf("short = %u\n", sizeof(short));  
printf("int = %u\n", sizeof(int));  
printf("long = %u\n", sizeof(long));  
printf("long long = %u\n", sizeof(long long)); 

Modifiez les lignes de votre programme

unsigned char *b = (unsigned char *)c; 
printf("%d\n", *(b + 8)); 

Et test simple (je sais que ce n'est pas garanti mais tous les compilateurs C que je connais le font de cette façon et je me fous des vieilles machines CDC ou UNISYS qui avaient des adresses et des pointeurs différents pour différer types de location de données

printf(" endianes test: %s\n", (*b + (unsigned)*(b + 1) * 0x100) == 400? "little" : "big"); 

Une autre remarque: il est seulement parce que dans votre programme c [0] == 400

2

Le code donne différentes sorties sur différents ordinateurs car sur certaines plateformes le type char est signé par défaut et sur d'autres il est non signé par défaut. Cela n'a rien à voir avec l'endianisme. Essayez ceci:

char *b = (char *)c; 
    printf("%d\n", (unsigned char)*(b+8)); // always prints 148 
    printf("%d\n", (signed char)*(b+8)); // always prints -108 (=-256 +148) 

La valeur par défaut dépend des paramètres de la plate-forme et du compilateur. Vous pouvez contrôler le comportement par défaut avec les options GCC -fsigned-char et -funsigned-char.