Identificateurs reserves de la bibliotheque standard
10 réponses
candide
Bonjour,
Les normes C90 et C99 stipulent :
----------------------------- 8< ----------------------------------
7.1.3 Reserved identifiers
[...]
— All identifiers with external linkage in any of the following
subclauses (including the future library directions) are always reserved
for use as identifiers with external linkage.
— Each identifier with file scope listed in any of the following
subclauses (including the future library directions) is reserved for use
as a macro name and as an identifier with file scope in the same name
space if any of its associated headers is included.
----------------------------- >8 ----------------------------------
Dois-je comprendre (même si ce n'est pas dit formellement me
semble-t-il) que je suis autorisé à écrire un programme comme ceci :
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
espie
In article <4870c685$0$15462$, candide wrote:
Bonjour,
Les normes C90 et C99 stipulent :
----------------------------- 8< ---------------------------------- 7.1.3 Reserved identifiers [...] — All identifiers with external linkage in any of the following subclauses (including the future library directions) are always reserved for use as identifiers with external linkage.
— Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included. ----------------------------- >8 ----------------------------------
Dois-je comprendre (même si ce n'est pas dit formellement me semble-t-il) que je suis autorisé à écrire un programme comme ceci :
external linkage -> ca inclut toutes les fonctions, dont str*, et quelques non-fonctions, comme errno.
In article <4870c685$0$15462$426a74cc@news.free.fr>,
candide <candide@free.invalid> wrote:
Bonjour,
Les normes C90 et C99 stipulent :
----------------------------- 8< ----------------------------------
7.1.3 Reserved identifiers
[...]
— All identifiers with external linkage in any of the following
subclauses (including the future library directions) are always reserved
for use as identifiers with external linkage.
— Each identifier with file scope listed in any of the following
subclauses (including the future library directions) is reserved for use
as a macro name and as an identifier with file scope in the same name
space if any of its associated headers is included.
----------------------------- >8 ----------------------------------
Dois-je comprendre (même si ce n'est pas dit formellement me
semble-t-il) que je suis autorisé à écrire un programme comme ceci :
----------------------------- 8< ---------------------------------- 7.1.3 Reserved identifiers [...] — All identifiers with external linkage in any of the following subclauses (including the future library directions) are always reserved for use as identifiers with external linkage.
— Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included. ----------------------------- >8 ----------------------------------
Dois-je comprendre (même si ce n'est pas dit formellement me semble-t-il) que je suis autorisé à écrire un programme comme ceci :
external linkage -> ca inclut toutes les fonctions, dont str*,
Oui mais la norme précise :
"for use as identifiers with external linkage".
Ma fonction strlen est "static" donc mon identificateur est en liaison interne et donc pas en liaison externe.
Antoine Leca
En news:4870c685$0$15462$, candide va escriure:
Les normes C90 et C99 stipulent : 7.1.3 Reserved identifiers [...]
Dois-je comprendre (même si ce n'est pas dit formellement me semble-t-il) que je suis autorisé à écrire un programme comme ceci : #include <stdio.h> static size_t strlen(const char *s) { /* mon code de strlen */ } int main(void) { printf("%un",strlen("toto")); return 0; }
Non, parce que size_t peut être incompatible avec unsigned (ce qu'un compilateur moderne devrait t'avoir signalé).
Par ailleurs, l'utilisation de strlen est déconseillée (on préferera strLen), mais reste conforme.
Antoine
En news:4870c685$0$15462$426a74cc@news.free.fr, candide va escriure:
Les normes C90 et C99 stipulent :
7.1.3 Reserved identifiers
[...]
Dois-je comprendre (même si ce n'est pas dit formellement me
semble-t-il) que je suis autorisé à écrire un programme comme ceci :
#include <stdio.h>
static size_t strlen(const char *s) { /* mon code de strlen */ }
int main(void) {
printf("%un",strlen("toto"));
return 0; }
Non, parce que size_t peut être incompatible avec unsigned (ce qu'un
compilateur moderne devrait t'avoir signalé).
Par ailleurs, l'utilisation de strlen est déconseillée (on préferera
strLen), mais reste conforme.
Les normes C90 et C99 stipulent : 7.1.3 Reserved identifiers [...]
Dois-je comprendre (même si ce n'est pas dit formellement me semble-t-il) que je suis autorisé à écrire un programme comme ceci : #include <stdio.h> static size_t strlen(const char *s) { /* mon code de strlen */ } int main(void) { printf("%un",strlen("toto")); return 0; }
Non, parce que size_t peut être incompatible avec unsigned (ce qu'un compilateur moderne devrait t'avoir signalé).
Par ailleurs, l'utilisation de strlen est déconseillée (on préferera strLen), mais reste conforme.
Antoine
candide
Antoine Leca a écrit
printf("%un",strlen("toto"));
Non, parce que size_t peut être incompatible avec unsigned
Qu'aurais-je dû écrire ? ceci par exemple :
printf("%lun",(unsigned long)strlen("toto"));
?
> > (ce qu'un > compilateur moderne devrait t'avoir signalé).
gcc -W -Wall -pedantic reste silencieux.
Par ailleurs, l'utilisation de strlen est déconseillée (on préferera strLen), mais reste conforme.
Merci de cette réponse.
Antoine Leca a écrit
printf("%un",strlen("toto"));
Non, parce que size_t peut être incompatible avec unsigned
Qu'aurais-je dû écrire ? ceci par exemple :
printf("%lun",(unsigned long)strlen("toto"));
?
>
> (ce qu'un
> compilateur moderne devrait t'avoir signalé).
gcc -W -Wall -pedantic reste silencieux.
Par ailleurs, l'utilisation de strlen est déconseillée (on préferera
strLen), mais reste conforme.
Le 15/07/08 02:54, dans <487bf562$0$12030$, « candide » a écrit :
Antoine Leca a écrit
printf("%un",strlen("toto"));
Non, parce que size_t peut être incompatible avec unsigned
Qu'aurais-je dû écrire ? ceci par exemple :
printf("%lun",(unsigned long)strlen("toto"));
Je pense que c'est :
printf("%zdn", strlen("toto"));
-- Éric Lévénez -- <http://www.levenez.com/> Unix is not only an OS, it's a way of life.
Antoine Leca
En news:C4A21E4C.D27C4%, Eric Levenez va escriure:
Le 15/07/08 02:54, dans <487bf562$0$12030$, « candide » a écrit :
Qu'aurais-je dû écrire ? ceci par exemple :
printf("%lun",(unsigned long)strlen("toto"));
printf("%zdn", strlen("toto"));
Les deux sont corrects. Le second nécessite que le printf() de la bibliothèque standard implémente C99 (par exemple, cela risque de ne pas être le cas avec Mingw, alors même que le compilateur utilisé clame être conforme C99...)
On peut aussi écrire
printf("%un",(unsigned)strlen("toto"));
mais c'est considéré comme moins bon en règle générale (car certains compilateurs permettent d'avoir des objets de taille supérieure à UINT_MAX, 64 Kio en 16 bits ou 4 Gio en 32 bits) ; la même raison fait préférer la seconde version à la première, car il est même possible d'avoir des implémentations (Win64 est la plus connue) où des objets peuvent avoir une taille supérieure à ULONG_MAX...
Antoine
En news:C4A21E4C.D27C4%usenet@levenez.com, Eric Levenez va escriure:
Le 15/07/08 02:54, dans <487bf562$0$12030$426a74cc@news.free.fr>,
« candide » a écrit :
Qu'aurais-je dû écrire ? ceci par exemple :
printf("%lun",(unsigned long)strlen("toto"));
printf("%zdn", strlen("toto"));
Les deux sont corrects. Le second nécessite que le printf() de la
bibliothèque standard implémente C99 (par exemple, cela risque de ne pas
être le cas avec Mingw, alors même que le compilateur utilisé clame être
conforme C99...)
On peut aussi écrire
printf("%un",(unsigned)strlen("toto"));
mais c'est considéré comme moins bon en règle générale (car certains
compilateurs permettent d'avoir des objets de taille supérieure à UINT_MAX,
64 Kio en 16 bits ou 4 Gio en 32 bits) ; la même raison fait préférer la
seconde version à la première, car il est même possible d'avoir des
implémentations (Win64 est la plus connue) où des objets peuvent avoir une
taille supérieure à ULONG_MAX...
En news:C4A21E4C.D27C4%, Eric Levenez va escriure:
Le 15/07/08 02:54, dans <487bf562$0$12030$, « candide » a écrit :
Qu'aurais-je dû écrire ? ceci par exemple :
printf("%lun",(unsigned long)strlen("toto"));
printf("%zdn", strlen("toto"));
Les deux sont corrects. Le second nécessite que le printf() de la bibliothèque standard implémente C99 (par exemple, cela risque de ne pas être le cas avec Mingw, alors même que le compilateur utilisé clame être conforme C99...)
On peut aussi écrire
printf("%un",(unsigned)strlen("toto"));
mais c'est considéré comme moins bon en règle générale (car certains compilateurs permettent d'avoir des objets de taille supérieure à UINT_MAX, 64 Kio en 16 bits ou 4 Gio en 32 bits) ; la même raison fait préférer la seconde version à la première, car il est même possible d'avoir des implémentations (Win64 est la plus connue) où des objets peuvent avoir une taille supérieure à ULONG_MAX...
Antoine
candide
Antoine Leca a écrit :
Les deux sont corrects. Le second nécessite que le printf() de la bibliothèque standard implémente C99 (par exemple, cela risque de ne pas être le cas avec Mingw, alors même que le compilateur utilisé clame être conforme C99...)
Je ne connais presque rien de spécifique à C99.
C90 est assez compliqué comme ça pour moi et me suffit.
On peut aussi écrire
printf("%un",(unsigned)strlen("toto"));
Je ne comprends pas ce que ça ajoute par rapport à
printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
mais c'est considéré comme moins bon en règle générale (car certains compilateurs permettent d'avoir des objets de taille supérieure à UINT_MAX, 64 Kio en 16 bits ou 4 Gio en 32 bits) ;
strlen() retourne un entier de type size_t et ce type n'est-il pas garanti pouvoir recevoir la taille du plus grand objet que l'implémentation peut créer ?
Antoine Leca a écrit :
Les deux sont corrects. Le second nécessite que le printf() de la
bibliothèque standard implémente C99 (par exemple, cela risque de ne pas
être le cas avec Mingw, alors même que le compilateur utilisé clame être
conforme C99...)
Je ne connais presque rien de spécifique à C99.
C90 est assez compliqué comme ça pour moi et me suffit.
On peut aussi écrire
printf("%un",(unsigned)strlen("toto"));
Je ne comprends pas ce que ça ajoute par rapport à
printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
mais c'est considéré comme moins bon en règle générale (car certains
compilateurs permettent d'avoir des objets de taille supérieure à UINT_MAX,
64 Kio en 16 bits ou 4 Gio en 32 bits) ;
strlen() retourne un entier de type size_t et ce type n'est-il pas
garanti pouvoir recevoir la taille du plus grand objet que
l'implémentation peut créer ?
Les deux sont corrects. Le second nécessite que le printf() de la bibliothèque standard implémente C99 (par exemple, cela risque de ne pas être le cas avec Mingw, alors même que le compilateur utilisé clame être conforme C99...)
Je ne connais presque rien de spécifique à C99.
C90 est assez compliqué comme ça pour moi et me suffit.
On peut aussi écrire
printf("%un",(unsigned)strlen("toto"));
Je ne comprends pas ce que ça ajoute par rapport à
printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
mais c'est considéré comme moins bon en règle générale (car certains compilateurs permettent d'avoir des objets de taille supérieure à UINT_MAX, 64 Kio en 16 bits ou 4 Gio en 32 bits) ;
strlen() retourne un entier de type size_t et ce type n'est-il pas garanti pouvoir recevoir la taille du plus grand objet que l'implémentation peut créer ?
espie
In article <487cb490$0$6783$, candide wrote:
Je ne comprends pas ce que ça ajoute par rapport à
printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
Et quelle taille ? printf est une fonction a nombre variable d'arguments, de prototype int printf(const char *, ...);
il n'y a donc pas de verif de type passe le format. Si tu es sur une plateforme ou size_t vaut unsigned long, ton printf ne marchera pas: il recuperera juste un unsigned int comme parametre.
Selon les cas: - tu peux avoir de la chance, si ton size_t est inferieur a UINT_MAX, et que les octets de tes valeurs sont dans le bon ordre, ca affichera la bonne valeur. - tu peux avoir moins de chance, et recuperer un 0 correspond aux octets de poids fort. - pour un printf plus complique, avec d'autres parametres derriere, ca va de toutes facons mettre la zone dans la lecture des parametres suivants. - si tu n'as vraiment pas de bol et que tu es sur une archi exotique, ca peut confuser ton programme, te faire lire une adresse de retour de travers, avoir des effets de bords sur d'autres variables du programme, voire finir en segfault.
In article <487cb490$0$6783$426a34cc@news.free.fr>,
candide <candide@free.invalid> wrote:
Je ne comprends pas ce que ça ajoute par rapport à
printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
Et quelle taille ? printf est une fonction a nombre variable d'arguments,
de prototype
int printf(const char *, ...);
il n'y a donc pas de verif de type passe le format. Si tu es sur une plateforme
ou size_t vaut unsigned long, ton printf ne marchera pas: il recuperera juste
un unsigned int comme parametre.
Selon les cas:
- tu peux avoir de la chance, si ton size_t est inferieur a UINT_MAX, et que
les octets de tes valeurs sont dans le bon ordre, ca affichera la bonne valeur.
- tu peux avoir moins de chance, et recuperer un 0 correspond aux octets de
poids fort.
- pour un printf plus complique, avec d'autres parametres derriere, ca va
de toutes facons mettre la zone dans la lecture des parametres suivants.
- si tu n'as vraiment pas de bol et que tu es sur une archi exotique, ca
peut confuser ton programme, te faire lire une adresse de retour de travers,
avoir des effets de bords sur d'autres variables du programme, voire finir
en segfault.
Je ne comprends pas ce que ça ajoute par rapport à
printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
Et quelle taille ? printf est une fonction a nombre variable d'arguments, de prototype int printf(const char *, ...);
il n'y a donc pas de verif de type passe le format. Si tu es sur une plateforme ou size_t vaut unsigned long, ton printf ne marchera pas: il recuperera juste un unsigned int comme parametre.
Selon les cas: - tu peux avoir de la chance, si ton size_t est inferieur a UINT_MAX, et que les octets de tes valeurs sont dans le bon ordre, ca affichera la bonne valeur. - tu peux avoir moins de chance, et recuperer un 0 correspond aux octets de poids fort. - pour un printf plus complique, avec d'autres parametres derriere, ca va de toutes facons mettre la zone dans la lecture des parametres suivants. - si tu n'as vraiment pas de bol et que tu es sur une archi exotique, ca peut confuser ton programme, te faire lire une adresse de retour de travers, avoir des effets de bords sur d'autres variables du programme, voire finir en segfault.
Antoine Leca
Tout-à-fait d'accord avec l'explication détaillée de Marc (que je ne vais pas recopier), sauf pour un détail:
En news:g5ift4$1ckv$, Marc Espie va escriure:
printf("%un",(unsigned)strlen("toto"));
Je ne comprends pas ce que ça ajoute par rapport à printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
<snip>
Si tu es sur une plateforme ou size_t vaut unsigned long,
... et que les long sur cette plateforme ont une taille ou une représentation différente des int ...
ton printf ne marchera pas: il recuperera juste un unsigned int comme parametre.
<etc., le reste inchangé>
Le détail est d'importance, car sur la plupart des machines de la période 1980-2010 (le règne des 32 bits), il n'y a _pas_ de différence entre int et long.
Et la pinaillerie de rajouter le (unsigned) comme je l'ai fait plus tôt n'a donc pas d'effet pratique sur « la plupart des machines ».
Le vrai souci, c'est que l'on voit bien, en particulier avec les machines à architecture 64 bits, que l'on arrive au bout de cette période, ou du moins qu'on commence à en voir le bout. Donc il devient urgent de bien prendre conscience de ce « détail », et de prendre les « bonnes » habitudes, em l'occurence comme explique Marc ne pas laisser un size_t comme argument variable si la fonction attend un unsigned (ou vice-versa).
Si vous voulez un signe supplémentaire que l'on va au-devant de problèmes, regardez l'attitude (opposée) qu'on pris les responsables des architectures : sur Unix, ils ont décidé d'affronter le problème le plus tôt possible, et donc ont forcé la conversion vers LP64, disociant int et long : donc beaucoup de programmeurs doivent modifier le code (mal écrit) pour que cela marche ; chez Microsoft --après avoir galèré trop longtemps avec les int trop petits du temps de DOS et Windows 3.x-- ils ont choisi ce que l'on peut appeler la politique de l'autruche, qui consiste à préserver le plus longtemps possible le confort des tailles identiques, donc long reste sur 32 bits pour Win64...
Antoine
Tout-à-fait d'accord avec l'explication détaillée de Marc (que je ne vais
pas recopier), sauf pour un détail:
En news:g5ift4$1ckv$1@biggoron.nerim.net, Marc Espie va escriure:
printf("%un",(unsigned)strlen("toto"));
Je ne comprends pas ce que ça ajoute par rapport à
printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
<snip>
Si tu es sur une plateforme ou size_t vaut unsigned long,
... et que les long sur cette plateforme ont une taille ou une
représentation différente des int ...
ton printf ne marchera pas:
il recuperera juste un unsigned int comme parametre.
<etc., le reste inchangé>
Le détail est d'importance, car sur la plupart des machines de la période
1980-2010 (le règne des 32 bits), il n'y a _pas_ de différence entre int et
long.
Et la pinaillerie de rajouter le (unsigned) comme je l'ai fait plus tôt n'a
donc pas d'effet pratique sur « la plupart des machines ».
Le vrai souci, c'est que l'on voit bien, en particulier avec les machines à
architecture 64 bits, que l'on arrive au bout de cette période, ou du moins
qu'on commence à en voir le bout. Donc il devient urgent de bien prendre
conscience de ce « détail », et de prendre les « bonnes » habitudes, em
l'occurence comme explique Marc ne pas laisser un size_t comme argument
variable si la fonction attend un unsigned (ou vice-versa).
Si vous voulez un signe supplémentaire que l'on va au-devant de problèmes,
regardez l'attitude (opposée) qu'on pris les responsables des architectures
: sur Unix, ils ont décidé d'affronter le problème le plus tôt possible, et
donc ont forcé la conversion vers LP64, disociant int et long : donc
beaucoup de programmeurs doivent modifier le code (mal écrit) pour que cela
marche ; chez Microsoft --après avoir galèré trop longtemps avec les int
trop petits du temps de DOS et Windows 3.x-- ils ont choisi ce que l'on peut
appeler la politique de l'autruche, qui consiste à préserver le plus
longtemps possible le confort des tailles identiques, donc long reste sur 32
bits pour Win64...
Tout-à-fait d'accord avec l'explication détaillée de Marc (que je ne vais pas recopier), sauf pour un détail:
En news:g5ift4$1ckv$, Marc Espie va escriure:
printf("%un",(unsigned)strlen("toto"));
Je ne comprends pas ce que ça ajoute par rapport à printf("%un",strlen("toto"));
puisque size_t est un type entier non signé.
<snip>
Si tu es sur une plateforme ou size_t vaut unsigned long,
... et que les long sur cette plateforme ont une taille ou une représentation différente des int ...
ton printf ne marchera pas: il recuperera juste un unsigned int comme parametre.
<etc., le reste inchangé>
Le détail est d'importance, car sur la plupart des machines de la période 1980-2010 (le règne des 32 bits), il n'y a _pas_ de différence entre int et long.
Et la pinaillerie de rajouter le (unsigned) comme je l'ai fait plus tôt n'a donc pas d'effet pratique sur « la plupart des machines ».
Le vrai souci, c'est que l'on voit bien, en particulier avec les machines à architecture 64 bits, que l'on arrive au bout de cette période, ou du moins qu'on commence à en voir le bout. Donc il devient urgent de bien prendre conscience de ce « détail », et de prendre les « bonnes » habitudes, em l'occurence comme explique Marc ne pas laisser un size_t comme argument variable si la fonction attend un unsigned (ou vice-versa).
Si vous voulez un signe supplémentaire que l'on va au-devant de problèmes, regardez l'attitude (opposée) qu'on pris les responsables des architectures : sur Unix, ils ont décidé d'affronter le problème le plus tôt possible, et donc ont forcé la conversion vers LP64, disociant int et long : donc beaucoup de programmeurs doivent modifier le code (mal écrit) pour que cela marche ; chez Microsoft --après avoir galèré trop longtemps avec les int trop petits du temps de DOS et Windows 3.x-- ils ont choisi ce que l'on peut appeler la politique de l'autruche, qui consiste à préserver le plus longtemps possible le confort des tailles identiques, donc long reste sur 32 bits pour Win64...
Antoine
-ed-
On 15 juil, 09:28, Eric Levenez wrote:
Je pense que c'est :
printf("%zdn", strlen("toto"));
[C99] "%zu" pour un size_t...
On 15 juil, 09:28, Eric Levenez <use...@levenez.com> wrote: