FAQ CConsultez toutes les FAQ
Nombre d'auteurs : 35, nombre de questions : 194, dernière mise à jour : 18 février 2018 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de www.developpez.com et de l'expérience personnelle des auteurs.
Je tiens à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez devenir rédacteur, lisez ceci .
Sur ce, je vous souhaite une bonne lecture.
- Quelle est la taille d'un char ?
- Quelle est la taille des différents types ?
- Que signifient signed et unsigned ?
- Quelle est la différence entre char, signed char et unsigned char ?
- Pourquoi mon compilateur ne connaît-il pas le type long long ?
- Quel est le rôle de l'opérateur sizeof ?
- Existe-t-il un type booléen en C ?
- Qu'est-ce que le type size_t ?
- Qu'est-ce que le type wchar_t ?
- Comment créer un synonyme d'un type existant ?
- Que signifie l'erreur « undefined reference to xxx » ou « symbol not found » ?
Par définition, sizeof(char) vaut 1, c'est-à-dire qu'un char représente un byte. Toutefois, contrairement à une idée répandue, en langage C un byte (multiplet et non octet) ne fait pas forcément 8 bits. La norme requiert néanmoins qu'un byte doit faire au moins 8 bits et la taille exacte d'un char, en bits, est donnée par la macro CHAR_BIT définie dans le fichier limits.h.
La norme n'impose pas la taille d'un type, cette taille dépend donc de l'implémentation. Toutefois la norme impose des plages minimales pour chaque type :
Code C : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | +--------------------+-----------------------+----------------------+----------------------+ | Type | min minimum imposé | max minimum imposé | => Taille min : | +--------------------+-----------------------+----------------------+----------------------+ | signed char | -127 | 127 | | +--------------------+-----------------------+----------------------+ 8 bits | | unsigned char | 0 | 255 | | +--------------------+-----------------------+----------------------+----------------------+ | short | -32767 | 32767 | | +--------------------+-----------------------+----------------------+ 16 bits | | unsigned short | 0 | 65535 | | +--------------------+-----------------------+----------------------+----------------------+ | int | -32767 | 32767 | | +--------------------+-----------------------+----------------------+ 16 bits | | unsigned int | 0 | 65535 | | +--------------------+-----------------------+----------------------+----------------------+ | long | -2147483647 | 2147483647 | | +--------------------+-----------------------+----------------------+ 32 bits | | unsigned long | 0 | 4294967295 | | +--------------------+-----------------------+----------------------+----------------------+ | long long | -9223372036854775807 | 9223372036854775807 | | +--------------------+-----------------------+----------------------+ 64 bits | | unsigned long long | 0 | 18446744073709551615 | | +--------------------+-----------------------+----------------------+----------------------+ |
Les valeurs effectives des limites pour chaque type sont définies par l'implémentation et se trouvent dans les fichiers limits.h (pour les entiers) et float.h (pour les flottants).
Ces mot-clés ne peuvent s'utiliser qu'avec les types entiers c'est-à-dire char, short (short int), int, long (long int) et long long (long long int). Ils permettent d'indiquer si le type supporte des valeurs négatives (signed) ou non (unsigned). Sur un type autre que char, signed est toujours facultatif.
Le type char désigne, selon l'implémentation, signed char ou unsigned char. Le type réel du type char doit être indiqué dans la documentation du compilateur.
Parce que ce type n'a été introduit qu'avec la norme C99. Vous utilisez probablement un compilateur non conforme à cette norme ou peut-être que les réglages de votre compilateur sont tels que seules les fonctionnalités C90 sont activées.
Il permet de connaître la taille, en bytes, d'une variable ou d'un type.
Avant la norme C99, il n'existait pas en C de type booléen à proprement parler, mais il est très simple à « créer » si le compilateur utilisé ne le propose pas déjà en utilisant :
Code C : | Sélectionner tout |
1 2 3 | #define BOOL int #define TRUE 1 #define FALSE 0 |
Code C : | Sélectionner tout |
1 2 3 | typedef enum { FALSE, TRUE } BOOL; |
La norme C99 introduit le type _Bool et l'en-tête <stdbool.h> définit les macros bool (_Bool), true (1) et false (0) ainsi que __bool_true_false_are_defined qui permet de savoir si les booléens sont nativement supportés.
Une solution permettant d'écrire du code compatible C99 consiste à utiliser les types natifs sur un compilateur conforme C99 et définir un type booléen maison dans le contraire. Par exemple :
Code C : | Sélectionner tout |
1 2 3 4 5 6 | #ifndef __bool_true_false_are_defined # define bool int # define true 1 # define false 0 # define __bool_true_false_are_defined #endif |
Ce type défini dans stddef.h (qui est inclus par de nombreux fichiers d'en-tête…) correspond au type de la valeur retournée par l'opérateur sizeof. La norme requiert que size_t soit un entier non signé, mais le type exact auquel il correspond dépend de l'implémentation.
wchar_t (wide character) est le type qui permet de représenter n'importe quel élément du jeu de caractères courant de l'environnement. Il peut être défini à l'aide d'un typedef ou être nativement supporté par le compilateur. À noter que char et wchar_t étant des types différents, un caractère « large » (un caractère de type wchar_t) ne s'écrit pas de la même façon qu'un simple caractère. Les caractères larges doivent toujours être précédés d'un L. Par exemple L'A', L'*' et L'1' sont des caractères larges. C'est valable également pour les chaînes de caractères larges, par exemple : L"Bonjour" au lieu de "Bonjour". De même, les fonctions de manipulation des caractères et/ou chaînes de caractères larges ne sont pas les mêmes que celles qui sont dédiées aux caractères et/ou chaînes de caractères simples bien que l'on puisse noter une certaine similitude au niveau des noms et des paramètres requis. Par exemple, pour les caractères et chaînes de caractères larges, on utilise wprintf à la place de printf, wcscpy à la place de strcpy, iswalpha à la place de isalpha, etc. Selon les fonctions que vous utilisez, vous devez inclure wchar.h et/ou wctype.h.
Le programme suivant montre un exemple d'utilisation des caractères larges.
Code c : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <stdio.h> #include <wchar.h> int main() { wchar_t ws[256]; wcscpy(ws, L"Hello"); wcscat(ws, L", world !"); wprintf(L"%s\n", ws); return 0; } |
Dans certains cas très simples, un #define peut déjà faire l'affaire (par exemple : #define ENTIER int). Dans des cas un peu plus complexes, il faudra définir le synonyme à l'aide du mot-clé typedef. Pour ce faire, il suffit, dans une déclaration valide d'une variable du type voulu, remplacer l'identifiant de la variable par le nom qu'on veut donner à son type puis de commencer la ligne par typedef.
Supposons par exemple que nous souhaitons définir un synonyme pour le type int en utilisant cette méthode. Nous allons donc donner un deuxième nom, ENTIER, à int.
- Prenons donc une déclaration valide d'une variable de type int : int x;
- Remplaçons l'identifiant de la variable (x) par le nom qu'on veut donner au type (ENTIER) : int ENTIER;
- Ajoutons enfin le mot-clé typedef : typedef int ENTIER;
Voici quelques exemples supplémentaires :
Code c : | Sélectionner tout |
1 2 3 4 5 6 7 | typedef int VECTEUR[3]; typedef void * POINTEUR; typedef struct { int value; } INTVALUE; VECTEUR u, v; /* int u[3], int v[3]; */ POINTEUR p1, p2; /* void * p1, * p2; */ INTVALUE n; /* struct { int value; } n; */ |
L'erreur « undefined reference to xxx » ou « symbol not found » est émise par l'éditeur de liens (linker en anglais) lorsqu'il ne trouve pas la définition d'un symbole déclaré dans une ou plusieurs unités de compilation. Les deux messages dénotent de la même erreur et la formulation employée dépend du compilateur.
Voici un code qui produit une telle erreur :
Code C : | Sélectionner tout |
1 2 3 4 5 6 7 | void f(void); int main(void) { f(); return 0; } |
main.c:5: undefined reference to `f'
collect2.exe: error: ld returned 1 exit status
Undefined symbols for architecture x86_64:
"_f", referenced from:
_main in ccpPQxzc.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Lorsqu'une telle erreur se produit, il faut vérifier :
- qu'un autre fichier source contient bien la définition du symbole ;
- que tous les fichiers source sont correctement ajoutés au projet et seront bien utilisés lors de l'édition des liens ;
- qu'une bibliothèque contient la définition du symbole ;
- que cette bibliothèque est correctement ajoutée au projet et sera bien utilisée lors l'édition des liens ;
- que la déclaration du symbole est correcte (par exemple, déclarer void setup(void); au lieu de void Setup(void);.
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.