2017-10-12 8 views
3
#include <stdio.h> 
int main() 
{ 
    short int a; 
    char c; 
    printf("%d %d %d",sizeof(a),sizeof(c),sizeof(c+a)); 
} 

Dans ce SIZEOF a est 2 octets de taille de caractère est 1 octet, mais je les additionner, il donne 4 octets. ce qu'il fait à l'intérieur de l'expression pour le rendre 4pourquoi ce sizeof (c + a) est de donner 4 octets au lieu de 3

+1

À côté: '% d' ==>'% zu' –

+4

comment diable est-ce que cela a eu autant de votes? –

+1

Ouais ... C'est curieux ... Étant donné que l'expression 'sizeof (c + a)' est un non-sens et inutile par lui-même. Eh bien, je suppose que certaines personnes sont juste surprises par les résultats comme le PO est. –

Répondre

3

sizeof renvoie la taille de la représentation de l'objet après qu'elle a été évaluée. L'expression c+a renvoie apparemment un int, qui est quatre octets. Je pense que ce que vous recherchez est:

sizeof(c) + sizeof(a)

11

Ajout d'un short int à un char se traduit par une int, ce qui est apparemment 4 octets sur votre système.

Ceci est un cas si "promotion d'entier". Voir In a C expression where unsigned int and signed int are present, which type will be promoted to what type? pour une explication. Les règles sont plutôt déroutantes, mais les réponses l'expliquent plutôt bien.

par 6.3.1.8 conversions arithmétiques habituelles de the C standard, la règle de conversion réelle est:

Si les deux opérandes ont le même type, aucune autre conversion est nécessaire.

Dans le cas contraire, si les deux opérandes ont signé les types entiers ou les deux ont types d'entiers non signés, l'opérande avec le type de rang de conversion inférieur entier est converti en type de l'opérateur avec rang plus.

Dans le cas contraire, si l'opérande est de type entier non signé a plus de rang ou égal au rang du type de l'autre opérande , l'opérande de type entier signé est converti en type de l'opérateur avec non signé nombre entier type.

Dans le cas contraire, si le type de l'opérateur avec le type entier signé peut représenter toutes les valeurs du type de l'opérateur avec le type non signé entier, l'opérande de type entier non signé est converti au type de opérande avec un type entier signé.

Sinon, les deux opérandes sont converties au type entier non signé
correspondant au type de l'opérande avec signé type entier.

Le résultat est 4, parce que, comme @WeatherVane noté dans les commentaires:

5.1.2.3 para 11 EXEMPLE 2 Dans l'exécution du fragmentchar c1, c2; /* ... */ c1 = c1 + c2;les promotions "entiers" exige que la machine abstraite Promouvoir la valeur de chaque variable à int size puis ajouter les deux ints et tronquer la somme. Mais il n'y a pas de troncature ici parce que la destination est inconnue.

+1

Etes-vous certain qu'il fait la promotion d'un int et pas un court? (Ne pas dire que vous avez tort, j'essaie juste de comprendre comment la norme spécifie la promotion) –

+0

@ChristianGibbons Si le code et la sortie affichés sont corrects, il * est promu en un int. Bien que je lis les règles, je pense aussi que cela pourrait être faux et que cela devrait être promu à un "court". Cela pourrait être un bug du compilateur. –

+2

@ChristianGibbons 'a + c' n'a été affecté à aucune variable cible. Les calculs arithmétiques sont promus à 'int'. –

3

Lorsque des types entiers comme char, short int, bool prennent moins de nombre d'octets que int, ces types de données sont automatiquement promus à int ou unsigned int lorsqu'une opération est effectuée sur eux.

C11 §6.3.1.1 booléens, les caractères et les entiers

Si un int peut représenter toutes les valeurs du type d'origine (comme limitée par la largeur , pour un champ binaire), la la valeur est convertie en int; sinon, il est converti en un entier non signé. Ceux-ci sont appelés les promotions entières . 58)

Ainsi, c+a sont converties au type int et le résultat a ce type commun d'opérandes qui est int.

En outre, le comportement de votre code est undefined, car vous avez utilisé le mauvais spécificateur de format.

, utilisez %zu au lieu de %d parce sizeof() retours size_t et size_t est unsigned.

C11 Standard: §7.21.6.1: Paragraphe 9:

Si une spécification de conversion est invalide, le comportement est non défini. 225) Si un argument n'est pas le bon type pour la spécification de conversion correspondante , le comportement n'est pas défini.

2

Pour incliné mathématiquement (et parce qu'il me vint à se demander si une telle chose pourrait jamais être vrai):

La mauvaise compréhension qui est OP est travaillé par est que

f (x) + f (y) = f (x + y)

ce qui n'est certainement pas vrai pour sizeof() pour les raisons que Tom souligne dans les commentaires.

La classe des fonctions pour lesquelles il est- vrai sont appelés Additive Maps

Des exemples typiques comprennent des cartes entre des anneaux, des espaces vectoriels, ou modules qui préservent le groupe additif.

+1

Fun mais en "C", sizeof est un opérateur de compilation et ils ne sont pas des fonctions. Retour à l'algèbre abstraite, les deux opérateurs "+" sont différents, l'un étant sur des valeurs entières non signées et l'autre étant sur des types donc je ne pense pas que vous ayez une carte. –

+1

@ tom-blodget yep s'amusait juste avec une question idiote :) Mise à jour de la réponse pour référencer votre entrée. –