Est-ce que quelqu’un sait pourquoi le type d’argument de putchar()
, fputc()
et putc()
n’est pas un caractère, mais le type d’argument de putwchar()
, fputwc()
et putwc()
est wchar_t
? Voir aussi ceci et cela .
La réponse est “inheritance” (ou “histoire”). Avant la norme C90, il n’y avait pas de prototypes de fonctions et tous les arguments de toutes les fonctions étaient soumis à des règles de promotion par défaut. Un caractère était donc automatiquement passé en tant que int
( short
était promu en int
aussi, et float
en double
, et de même pour les types non signés ). La norme ne pouvait pas se permettre de casser le code existant, elle a donc conservé ce type pour ces fonctions. Cela fait très peu de différence dans la pratique. La valeur que vous transmettez sera traitée comme un type de caractère même si vous transmettez une valeur hors limites. La spécification de fputc(int c, FILE *stream)
dit:
La fonction
fputc
écrit le caractère spécifié parc
(converti en caractèreunsigned char
) dans le stream de sortie pointé parstream
…
§6.5.2.2 Appels de fonction
¶6 Si l’expression qui désigne la fonction appelée a un type qui n’inclut pas de prototype, les promotions d’entier sont effectuées sur chaque argument, et les arguments de type float sont promus au double. Celles-ci sont appelées les promotions d’arguments par défaut. …
¶7… La notation de points de suspension dans un déclarateur de prototype de fonction provoque l’arrêt de la conversion du type d’argument après le dernier paramètre déclaré. Les promotions d’argument par défaut sont effectuées sur les arguments de fin.
Les promotions entières sont définies au § 6.3.1.
¶2 Les éléments suivants peuvent être utilisés dans une expression partout où un
int
ou ununsigned int
peut être utilisé:
- Un object ou une expression de type entier (autre que
int
ouunsigned int
) dont le rang de conversion d’entier est inférieur ou égal au rang d’int
et deunsigned int
.- Un champ de bits de type
_Bool
,int
,signed int
ouunsigned int
.Si un
int
peut représenter toutes les valeurs du type d’origine (comme le limite la largeur, pour un champ de bits), la valeur est convertie en unint
; sinon, il est converti en ununsigned int
. Celles-ci sont appelées promotions entières . 58) Tous les autres types ne sont pas modifiés par les promotions de nombre entier.¶3 Les promotions sur les entiers conservent la valeur, y compris le signe. Comme discuté plus tôt, si un caractère “simple” est traité comme signé est défini par l’implémentation.
58) Les promotions d’entier sont appliquées uniquement: dans le cadre des conversions arithmétiques habituelles, à certaines expressions d’argument, aux opérandes des opérateurs unaire
+
,-
et~
, et aux deux opérandes des opérateurs de décalage, spécifiés par leurs opérateurs respectifs. sous-paragraphes.
Les rangs entiers sont définis au ¶1 de la section en 10 points.
Je pense que la réponse de Jonathan est trop simple. Les choses sont légèrement plus rationnelles. Je pense qu’aucune des fonctions de bibliothèque manipulant des caractères uniques ne fonctionne avec char
(uniquement avec int
), car même si certaines d’entre elles n’utilisent pas EOF
, nous ne pouvons pas définir son caractère char
sans obtenir des avertissements de conversion de type tels que
void f(char c) { ... ... char x = 't'; f((unsigned char)x); ... warning: conversion to 'char' from 'unsigned char' may change the sign of the result
(Parce que les gens transtypent généralement char non signé pour garantir la portabilité du code, compte tenu du fait que la signature de char
est indéfinie.) La seule option était donc de le rendre int
.