Litterales
Les valeurs entières.
Les operations entre deux valeurs nécessitent de trouver un type commun entre les deux opérandes, de convertir chacun des opérandes vers ce type puis retourne le résulatat de l’opération vers ce type commun.
Le type d’un litéral entier est de type int
, sauf si un int
ne peut
pas le contenir auquel cas il est converti vers un type défini par l’implémentation
qui peut le contenir :
#include <stdio.h>
#define ptype(val) printf("%lld est de type ", val); _Generic(val, \
signed char: printf("signed char"), \
unsigned char: printf("unsigned char"), \
signed short: printf("signed short"), \
unsigned short: printf("unsigned short"), \
signed: printf("signed int"), \
unsigned: printf("unsigned int"), \
signed long: printf("signed long"), \
unsigned long: printf("unsigned long"), \
signed long long: printf("signed long long"), \
unsigned long long: printf("unsigned long long"), \
default: printf("not found") \
); \
printf("\n");
int main(void) {
ptype(0); // signed int
ptype(12); // signed int
ptype(12l); // signed int
ptype(-12); // signed int
ptype(123); // signed int
ptype(130); // signed int
ptype(-130); // signed int
ptype(1000); // signed int
ptype(10000000000); // signed long long
ptype(10000000000000000000); // signed long long
}
Affichage possibles
0 est de type signed int
12 est de type signed int
12 est de type signed long
-12 est de type signed int
123 est de type signed int
130 est de type signed int
-130 est de type signed int
1000 est de type signed int
10000000000 est de type signed long
-8446744073709551616 est de type unsigned long long
A noter que pour afficher correctement 10000000000000000000, il aurrait fallu utiliser
printf("%llu est de type ", val);
au lieu de
printf("%lld est de type ", val);
, mais
dans ce cas on n’aurait pas pu afficher correctement
les nombres negqtifs comme -12.
Modificateurs de valeurs littérales
Pour pouvoir transformer un littéral en un type différent à int
on peut ajouter un modificateur à sa droite, soit u
ou U
pour unsigned
,
l
ou L
pour un long
et ll
ou LL
pour long long
. Il n’est pas possible d’avoir un entier
littéral de type “short” ou “char”. Meme une
valeur littérale de la forme 'x'
est considéré
comme étant de type int
.
#include <stdio.h>
#define ptype(val) printf("%d est de type ", val); _Generic(val, \
signed char: printf("signed char"), \
unsigned char: printf("unsigned char"), \
signed short: printf("signed short"), \
unsigned short: printf("unsigned short"), \
signed: printf("signed int"), \
unsigned: printf("unsigned int"), \
signed long: printf("signed long"), \
unsigned long: printf("unsigned long"), \
signed long long: printf("signed long long"), \
unsigned long long: printf("unsigned long long"), \
default: printf("not found") \
); \
printf("\n");
int main(void) {
ptype(12); // signed int
ptype(13u); // unsigned int
ptype(14l); // signed long
ptype(15ul); // unsigned long
ptype(16ll); // signed long long
ptype(17ull); // unsigned long long
ptype(18ULL); // unsigned long long
}
Caractères isolés
Les caractères sont de type int
, Il est possible
d’avoir des caractères sur 16 et 32 bits avec les préfixes u
et U
,
de type char16_t
et char42_t
,
et des caractères de type wchar_t
avec le préxie ‘L’. En C23 il
sera possible d’avoir le prefixe u8
pour avoir des caractères
sur 8 bits de type char8_t
.
#include <stdio.h>
#define ptype(val) printf("%d est de type ", val); _Generic(val, \
signed char: printf("signed char"), \
unsigned char: printf("unsigned char"), \
signed short: printf("signed short"), \
unsigned short: printf("unsigned short"), \
signed: printf("signed int"), \
unsigned: printf("unsigned int"), \
signed long: printf("signed long"), \
unsigned long: printf("unsigned long"), \
signed long long: printf("signed long long"), \
unsigned long long: printf("unsigned long long"), \
default: printf("not found") \
); \
printf("\n");
int main(void) {
ptype('a');
ptype(u'b');
ptype(U'c');
ptype(L'd');
}
Affichage possible
97 est de type signed int
98 est de type unsigned short
99 est de type unsigned int
100 est de type signed int
A noter que les types char
, unsigned char
et signed char
sont de types différents, le premier peut être signé ou non selon l’implémentation et il est de type « caractère » et sert à afficher du texte, alors que signed char
et unsigned char
sont des types entiers et servent a stocker des nombres sur un seul octet.
#include <stdio.h>
#define ptype(val) printf("%d est de type ", val); _Generic(val, \
signed char: printf("signed char"), \
unsigned char: printf("unsigned char"), \
signed short: printf("signed short"), \
unsigned short: printf("unsigned short"), \
signed: printf("signed int"), \
unsigned: printf("unsigned int"), \
signed long: printf("signed long"), \
unsigned long: printf("unsigned long"), \
signed long long: printf("signed long long"), \
unsigned long long: printf("unsigned long long"), \
default: printf("not found") \
); \
printf("\n");
int main(void) {
ptype((char)'a'); // 97 est de type char
ptype((signed char)'b'); // 98 est de type signed char
ptype((unsigned char)'c'); // 99 est de type unsigned char
ptype('d'); // 100 est de type signed int
puts("");
ptype((short)12); // 12 est de type signed short
ptype((signed short)13); // 13 est de type signed short
ptype((unsigned short)14); // 14 est de type unsigned short
puts("");
ptype((int)20); // 20 est de type signed int
ptype((signed int)21); // 21 est de type signed int
ptype((unsigned int)22); // 22 est de type unsigned int
}