Voici le code suivant écrit en c à l'aide de CodeBlocks:
#include <stdio.h>
void main() {
char c;
int i = 65;
c = i;
printf("%d\n", sizeof(c));
printf("%d\n", sizeof(i));
printf("%c", c);
}
Pourquoi lors de l'impression de la variable c après qu'elle a été affectée avec une valeur int ( c = i ), il n'est pas nécessaire de faire un casting?
3 Réponses :
Cette affectation est effectuée sur des types compatibles, car char n'est pas beaucoup plus qu'un entier d'un seul octet, alors que int est généralement de type entier de 4 octets (dépendant de la machine). Néanmoins, cette conversion (implicite) ne nécessite pas de conversion, mais vous risquez de perdre certaines informations (les octets supérieurs seraient tronqués).
Ce ne sont pas des types compatibles car ce terme est défini par le standard C. L'affectation est définie en raison de règles spécifiques pour les affectations et les conversions automatiques, et non en raison de la compatibilité des types.
Un cast est un moyen de forcer explicitement une conversion. Vous n'avez besoin de transtypages que lorsqu'aucune conversion implicite n'a lieu ou lorsque vous souhaitez que le résultat ait un autre type que ce que la conversion implicite produirait.
Dans ce cas, le standard C nécessite une conversion implicite via la règle de l'opérateur d'affectation (C11 6.5.16.1/2):
Dans affectation simple (=), la valeur de l'opérande de droite est convertie en le type du expression d'affectation et remplace la valeur stockée dans l'objet désigné par la gauche opérande.
char et int sont tous deux des types entiers. Ce qui à son tour signifie que dans ce cas, les règles de conversion des entiers sont implicitement invoquées:
6.3.1.3 Entiers signés et non signés
Lorsqu'une valeur de type entier est convertie en un autre type entier autre que _Bool, si la valeur peut être représentée par le nouveau type, il est inchangé.
Sinon, si le nouveau type n'est pas signé, la valeur est convertie en ajoutant ou soustraire une valeur de plus que la valeur maximale pouvant être représentée dans le nouveau type jusqu'à ce que la valeur soit dans la plage du nouveau type.
Sinon, le nouveau type est signé et la valeur ne peut pas y être représentée; soit le le résultat est défini par l'implémentation ou un signal défini par l'implémentation est émis.
Dans votre cas, le nouveau type char peut être signé ou non signé selon le compilateur. La valeur 65 peut être représentée par char quelle que soit la signature, donc le premier paragraphe ci-dessus s'applique et la valeur reste inchangée. Pour d'autres valeurs plus importantes, vous pourriez vous retrouver avec le cas "la valeur ne peut pas être représentée" à la place.
Il s'agit d'une conversion valide entre les types entiers, aucune conversion n'est donc nécessaire.
Veuillez noter qu'à proprement parler, le résultat de sizeof (c) etc est de type size_t et d'imprimer celui-ci correctement avec printf , vous devez utiliser le spécificateur % zu .
Vous voudrez peut-être préciser le besoin de transtypages dans les 2 premières instructions printf car % d attend un int , pas un size_t .
@chqrlie a ajouté une note à ce sujet.
Vous pourriez expliquer un peu pourquoi l'impression de c ne nécessite pas de conversion alors que "% d" attend un int . La valeur est convertie en int sans une variable int impliquée.
@Gerhardh Comment utiliser printf n'est pas vraiment pertinent pour la question. Il y a beaucoup de messages à ce sujet ailleurs sur SO.
C'est peut-être un peu flou mais pour moi la partie "Pourquoi lors de l'impression de c ..." semble être la question principale.
Je viens de voir que cela a été ajouté par la suite et le montage n'a même pas été fait par l'auteur de la question. Dans ce cas, vous avez raison, bien sûr.
Examinons votre programme:
char c; int i = 65; c = i; Il n'y a pas besoin de transtypage dans cette affectation car le type entier int de la variable i est implicitement converti en type entier de la destination . La valeur 65 peut être représentée par le type char , cette affectation est donc entièrement définie. printf ("% d \ n", sizeof (c)); le spécificateur de conversion % d attend une valeur int . sizeof (c) a la valeur 1 par définition, mais avec le type size_t , qui peut être supérieur à int . Vous devez utiliser un cast ici: printf ("% d \ n", (int) sizeof (c)); ou éventuellement utiliser un spécificateur de conversion spécifique à C99: printf ("% zu \ n ", taille de (c)); printf ("% d \ n", sizeof (i)); Même remarque que ci-dessus. La sortie sera définie par l'implémentation, mais la plupart des systèmes actuels ont un int 32 bits et des octets 8 bits, donc une taille de 4 . printf ("% c", c); Le passage d'un char comme argument de variable à printf provoque d'abord le char valeur à promouvoir en int (ou unsigned int ) et transmise comme telle. La promotion vers unsigned int se produit sur des plates-formes extrêmement rares où char est non signé et a la même taille que int . Sur d'autres plates-formes, le cast n'est pas nécessaire car % c attend un argument int . Notez également que main doit être défini avec un type de retour int.
Voici une version modifiée: p >
#include <stdio.h>
#include <limits.h>
int main() {
char c;
int i = 65;
c = i;
printf("%d\n", (int)sizeof(c));
printf("%d\n", (int)sizeof(i));
#if CHAR_MAX == UINT_MAX
/* cast only needed on pathological platforms */
printf("%c\n", (int)c);
#else
printf("%c\n", c);
#endif
return 0;
}
quelle est la question?
C n'est pas fortement typé.
Votre
printfutilise des spécificateurs de format incorrects pour les valeurs desizeof. Vous devez soit convertir les valeurs enint, soit changer les formats en% zu. Sinon, le code ne sera pas portable.@AbirBhattacharya: vous pouvez accepter l'une des réponses en cliquant sur la coche grise sous son score.