(Cette réponse concerne le côté C++ des choses, mais le problème de l'extension des signes existe aussi en C).
Manipuler les trois char
types ( signed
, unsigned
y char
) est plus délicat qu'il n'y paraît au premier abord. Les valeurs comprises entre 0 et SCHAR_MAX
(qui est de 127 pour un appareil 8-bit char
) sont faciles :
char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;
Mais, quand somevalue
est en dehors de cette plage, il ne passe que par unsigned char
vous donne des résultats cohérents pour le "même" char
dans les trois types :
char c = somevalue;
signed char sc = c;
unsigned char uc = c;
// Might not be true: int(c) == int(sc) and int(c) == int(uc).
int nc = (unsigned char)c;
int nsc = (unsigned char)sc;
int nuc = (unsigned char)uc;
// Always true: nc == nsc and nc == nuc.
Ceci est important lorsque vous utilisez des fonctions de ctype.h tels que isupper
o toupper
en raison de l'extension du signe :
char c = negative_char; // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n); // Undefined behavior.
Notez que la conversion en int est implicite ; ceci a le même UB :
char c = negative_char;
bool b = isupper(c);
Pour corriger cela, passez par unsigned char
ce qui est facilement réalisable en enveloppant ctype.h fonctionne grâce à safe_ctype :
template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }
//...
char c = CHAR_MIN;
bool b = safe_ctype<isupper>(c); // No UB.
std::string s = "value that may contain negative chars; e.g. user input";
std::transform(s.begin(), s.end(), s.begin(), &safe_ctype<toupper>);
// Must wrap toupper to eliminate UB in this case, you can't cast
// to unsigned char because the function is called inside transform.
Cela fonctionne car toute fonction prenant l'un des trois types de caractères peut également prendre les deux autres types de caractères. Cela conduit à deux fonctions qui peuvent manipuler n'importe lequel des types :
int ord(char c) { return (unsigned char)c; }
char chr(int n) {
assert(0 <= n); // Or other error-/sanity-checking.
assert(n <= UCHAR_MAX);
return (unsigned char)n;
}
// Ord and chr are named to match similar functions in other languages
// and libraries.
ord(c)
donne toujours une valeur non-négative, même si on lui passe une valeur négative. char
ou négative signed char
- et chr
prend n'importe quelle valeur ord
produit et rend exactement la même char
.
Dans la pratique, je me contenterais probablement de faire un casting à travers unsigned char
au lieu de les utiliser, mais ils enveloppent succinctement le casting, fournissent un endroit pratique pour ajouter la vérification d'erreur pour les int
-to- char
et seraient plus courtes et plus claires lorsque vous devez les utiliser plusieurs fois à proximité les unes des autres.
3 votes
@Matt : ce serait une bonne idée d'être plus concret. demander une généralisation ne fait qu'inviter des réponses généralisées qui sont sans objet ou même correct pour votre tâche. gardez à l'esprit que lorsque vous devez demander, vous n'en savez probablement pas assez pour généraliser correctement.
1 votes
@Alf P. Steinbach : La question initiale était vague concernant la langue. Avec des mots-clés
c
yc++
je pense que les réponses confrontant les deux langues sont raisonnables.11 votes
D'après ma vaste expérience sur d'autres forums techniques, mon intuition est que le PO vraiment signifie "comment puis-je prendre la représentation textuelle d'un nombre (en base 10) et la convertir en nombre correspondant ?". D'une manière générale, les néophytes du C et du C++ ont généralement incroyablement des idées floues sur la façon dont le texte fonctionne dans ces langues et sur ce qu'il faut faire.
char
signifie vraiment.4 votes
@KarlKnechtel : Si c'est vrai (je le donne à peu près à 50/50 car beaucoup des premiers tutoriels encouragent aussi l'obtention de valeurs ASCII à partir de caractères, même si l'ASCII ne couvre pas toute la gamme), le PO doit être clair - mais c'est un double de stackoverflow.com/questions/439573/ .
6 votes
Le PO avait trois heures pour clarifier cette question et n'a pas réussi à le faire. En l'état, il n'y a aucun moyen de savoir ce qui est réellement demandé. Voté pour fermer.
0 votes
C'est probablement un double de quelque chose dans les deux cas, en fait...
0 votes
Duplicata possible de Caractères en nombres entiers en C
0 votes
Notez que même si vous pouvez faire un casting implicite dans les deux sens quand il s'agit de int et char, il y a des choses vraiment importantes à savoir:1)selon la situation, vous pouvez perdre le signe moins de votre nombre (stocké comme un char) si vous ne faites pas attention. C'est pourquoi il y a un char signé et un char non signé;2)sizeof(char) = 1Byte (toujours ; ici j'exclue le caractère WIDE, qui peut être plus de 8bits) mais sizeof(int) = au moins 4Bytes ! Char est un type entier avec quelques restrictions. Je vous conseille d'éviter d'utiliser les chars pour les calculs mathématiques, à moins que vous n'en ayez vraiment besoin.