2009-12-05 8 views
2

Je veux imprimer la valeur de b [FFFC] comme ci-dessous,variable de type court étendue automatiquement au type entier?

short var = 0xFFFC; 
printf("%d\n", b[var]); 

Mais en fait imprimer la valeur de b [FFFF FFFC].

Pourquoi cela se produit-il?

Mon ordinateur est exploité par Windows XP en architecture 32 bits.

+0

quel est votre compilateur? Peut-être votre compilateur ne supporte pas 'short' – SjB

+2

me citer un compilateur C unique dans le monde qui ne supporte pas le type' short' ... –

+0

@Pakosz refroidisse ... @ SjB short est garanti C Standard universellement ... comme dans: c'est le couteau armé de vaches qui pleut, mais vous avez toujours votre short = 16bits sur le langage C. Cela et long = 32bit, etc, etc, etc ... int, dépend de la machine, cependant. – jpinto3912

Répondre

7

short est un type signé. C'est 16 bits sur votre implémentation. 0xFFFC représente la constante d'entier 65,532, mais lorsqu'il est converti en une valeur signée de 16 bits, il en résulte -4. Ainsi, votre ligne short var = 0xFFFC; définit var à -4 (sur votre implémentation). 0xFFFFFFFC 0xFFFFFF est une représentation de 32 bits de -4. Tout ce qui se passe est que votre valeur est convertie d'un type à un type plus grand, afin de l'utiliser comme un indice de tableau. Il conserve sa valeur, qui est -4.

Si vous voulez vraiment accéder à l'élément 65,533rd de votre tableau, vous devez soit:

  • utiliser un type plus grand pour var. int suffira sur Windows 32 bits, mais en général size_t est un type non signé qui est garanti assez grand pour les index de tableau non négatifs.
  • utiliser un unsigned short, ce qui juste vous donne assez de place pour cet exemple, mais se passera mal si vous voulez obtenir un autre 4 pas en avant.
+0

J'avais presque fini de taper presque mot à mot la même chose sauf pour dire que le compilateur a probablement émis un avertissement pour dire que 0xFFFC n'était pas une valeur courte valide - les avertissements sont là pour une raison - ne les ignorez pas. – Dipstick

+1

Il pourrait aussi utiliser le type 'size_t', qui est le type donné par la norme pour stocker les index de tableaux! Sérieusement, les gens, comment se fait-il que personne n'utilise 'size_t' quand ils sont supposés le faire? –

+0

size_t n'était pas toujours là, tant de gens ont des connaissances anciennes, ou apprennent de vieux livres/tutoriels/etc. Même sur certains compilateurs intégrés, vous n'obtenez pas size_t. – McPherrinM

0

Vous vous attendiez à stocker juste une variable de 16 bits dans une mémoire alignée 32 bits ... vous voyez, chaque adresse de mémoire contient un entier 32 bits (matériel).

Le FFFF supplémentaire vient du fait que court est une valeur signé, et lorsqu'ils sont affectés à int (à l'appel de printf), il est arrivé signé étendu. Lors de l'extension de deux compléments de 16 à 32 bits, l'extension est effectuée en répliquant le dernier bit N sur tous les autres M-N à sa gauche. Bien sûr, vous n'aviez pas l'intention de le faire. Par conséquent, dans ce cas, vous êtes intéressé par les positions de tableau absolues. Par conséquent, vous devez déclarer votre indexeur en tant que non signé.

1

Dans les compilateurs actuels, nous ne pouvons pas utiliser short (16 bits) si l'écriture short utilise 32 bits.
par exemple i compilez même code avec gcc4 dans Ubuntu Linux 32 bits:

int main(int argc, char** argv) 
{ 
    short var = 0xFFFC; 
    printf("%x\n", var); 
    printf("%d\n", var); 
    return (EXIT_SUCCESS); 
} 

et la sortie est:

fffffffc 
-4 

vous pouvez voir jeter court à 32bit normal et utiliser l'extension de signe en complément de 2

+0

vous conclusion de l'observation est fausse ... court var est 16bits. Faites une boucle var ++, voir où elle déborde. – jpinto3912

+0

@ jpinto3912 Quelle est votre conclusion? printf ne peut pas afficher les données 16 bits? si cela comment 'char c = 'c'; printf ("% x", c); ' – SjB

+0

ne veut pas voter en bas. Mais: (I) les compilateurs actuels * peuvent * utiliser court. "(II) la question ne portait pas sur printf, mais sur l'indexation d'un tableau avec le type de données" court "(... et je me suis trompé au début). III) printf peut afficher des données 16 bits, mais le spécificateur de type 'h' est nécessaire, par exemple avec '% hx' –

1

utilisation % hx ou% hd au lieu d'indiquer que vous avez une variable courte, par exemple:

printf("short hex: %hx\n", var);  /* tell printf that var is short and print out as hex */ 

EDIT: Uups, j'ai eu la mauvaise question. Il ne s'agissait pas de printf() comme je le pensais. Donc, cette réponse pourrait être un peu OT.

Nouveau: Parce que vous utilisez var comme un indice à un tableau, vous devez déclarer comme court non signé (au lieu de court):

unsigned short var = 0xFFFC; 
printf("%d\n", b[var]); 

Le « court var » pourrait être interprété comme un nombre négatif.

Pour être plus précis:

Vous êtes « underflowing » dans la plage de valeurs négatives: les valeurs dans la plage de 0x0000 jusqu'à 0x7FFF seront OK. Mais les valeurs de 0x8000 jusqu'à 0xFFFF seront négatives.

Voici quelques exemples de var utilisé comme un indice de tableau b []:

short var=0x0000;; // leads to b[0]  => OK 
short var=0x0001; // leads to b[1]  => OK 
short var=0x7FFF; // leads to b[32767] => OK 
short var=0x8000; // leads to b[-32768] => Wrong 
short var=0xFFFC; // leads to b[-4]  => Wrong 

short var=32767; // leads to the same as b[0x7FFF] => OK 
short var=32768; // compile warning or error => overflow into 32bit range 
+1

quelle est la raison pour laquelle b [FFFC] est converti en b [FFFFFFFC]? – SjB

+0

il ne convertit pas en b [ 0xFFFFFFFC] Pour être pointilleux: il ne convertit pas du tout Il est interprété/évalué comme b [-4] –

1

En tant que mise à jour sur les types de données du C disponibles, consultez here. Il y a une règle, et qui concerne l'utilisation de C, certains types de données sont promus à leur type intégral, par exemple

 
char ch = '2'; 
int j = ch + 1; 

Maintenant, regardez la partie droite (côté droit à la main) de l'expression et notez que le ch sera automatiquement promu comme int afin de produire les résultats souhaités sur le LHS (LHS) de l'expression. Quelle serait la valeur de j? Le code ASCII pour '2' est 50 décimal ou 0x32 hexadécimal, ajouter 1 dessus et la valeur de j serait 51 décimal ou 0x33 hexadécimal.

Il est important de comprendre cette règle et cela explique pourquoi un type de données serait «promu» à un autre type de données.

Qu'est-ce que le b? C'est un tableau que je présume qui a 655532 éléments corrects?

Quoi qu'il en soit, en utilisant un spécificateur de format %d est pour de type int, la valeur se est promu à un int, d'une part, et d'autre part l'indice de tableau est de type int, d'où l'utilisation du short var été promu et depuis la taille des données d'un int est de 4 octets, il a été promu et donc vous voyez le reste de la valeur 0xFFFF 0xFFFC.

C'est là l'utilisation de coulée arrive, pour dire au compilateur de coulé un type de données à un autre qui explique en même temps à la réponse de Gregory Pakosz ci-dessus.

Espérons que cela aide, Cordialement, Tom.

+0

+1 Enfin, une réponse qui mentionne la promotion de type Après la question C cet après-midi où tout le monde (en question et réponses) utilisait "déclaré" pour signifier "défini", je commençais à désespérer –

+1

@pascal: non tu n'as pas raison sur le terme "déclaration" Quand tu écris "short var = 0xFFFC" c'est une déclaration et une définition et une initialisation en même temps En C vous devez utiliser "extern court var" pour exprimer "déclaration seulement". –

+0

@ Vokuhila-Oliba: +1 pour votre commentaire ci-dessus! Veuillez consulter la section 1 de la FAQ portant spécifiquement sur les déclarations, les définitions des questions 1.11, 1.25 pour les clarifications. – t0mm13b

0

Au sujet de votre question que vous avez déjà deviné ce qui se passe ici: oui, une valeur de type short est « étendu automatiquement » à une valeur de type int. Ce processus est appelé promotion intégrale. Voilà comment cela fonctionne toujours en langage C: chaque fois que vous utilisez une valeur intégrale inférieure à int, cette valeur est toujours implicitement promue à une valeur de type int (les valeurs non signées peuvent être promues à unsigned int). La valeur elle-même ne change pas, bien sûr, seul le type de la valeur est changé. Dans votre exemple ci-dessus, la valeur short 16 bits représentée par le modèle 0xFFFC est la même que la valeur 32 bits int représentée par le modèle 0xFFFFFFFC, qui est -4 en décimales. Cela, BTW, rend le reste de votre question sonore plutôt étrange: promotion ou non, votre code tente d'accéder à b[-4]. La promotion au int ne change rien.

Questions connexes