Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

%zd et autres questions ...

8 réponses
Avatar
Pierre Maurette
Salut,
Je fais tourner un petit truc sur diverses machines/OS/compilateurs
(c'est le but). En x86-32, gcc 3.2 et Borland 5.6. En x86-64, gcc 3.3
et VC8 (en mode 64).

#include"stdio.h"
#include"stdlib.h"

/*
#define AFF_SIZE(a) printf("sizeof("#a"): %zd\n", sizeof(a));
*/
#define AFF_SIZE(a) printf("sizeof("#a"): %u\n", (unsigned)sizeof(a));

int main(void)
{
typedef void (*fptr)(void);
size_t s1 = sizeof(fptr);
size_t s2 = sizeof(void(*)(void));
printf("%d\t%d\n", (int)s1, (int)s2);
AFF_SIZE(char);
/* etc. */
AFF_SIZE(void*);
AFF_SIZE(void(*)(void));
AFF_SIZE(fptr);
return 0;
}

1 - Je fais souvent des conneries dans les macros. Quid de celle-ci ? A
part qu'elle fait n'importe quoi si l'argument n'est pas un type valide
*au run-time*. C'est pas bien grave (ce genre de code n'a de sens que
compilé et exécuté directement). Je vais voir d'ailleurs si on peut le
faire uniquement avec le préprocesseur.

2 - La norme semble indique z comme modificateur de longueur pour des
size_t. Or, seul gcc 3.3 *sous Linux* l'accepte et même le demande. Il
accepte également Z. D'où le cast qui évite partout les warnings. Les
autres affichent %zd, %zu, %z etc. Why ?

3 - Tous acceptent (en macro ou pas) sizeof(void(*)(void)). Mais gcc
3.3 sous Linux (et Eclipse/CDT que je teste à nouveau) râle. En fait,
c'est un truc nommé "Programme d'indexation C/C++", avec "Signaler les
erreurs de syntaxe" coché qui gueule :
Erreur du programme d'indexation C/C++ : Erreur de syntaxe détectée
dans le fichier
Il se calme avec le typedef et fptr. Est-ce une faiblesse du "Programme
d'indexation C/C++" ?
Merci des lumières ...

--
Pierre

8 réponses

Avatar
AG
Bonjour,

Pierre Maurette wrote:

2 - La norme semble indique z comme modificateur de longueur pour des
size_t. Or, seul gcc 3.3 *sous Linux* l'accepte et même le demande. Il
accepte également Z. D'où le cast qui évite partout les warnings. Les
autres affichent %zd, %zu, %z etc. Why ?
%z, c'est pas du C99 par hasard ?


AG.

Avatar
Pierre Maurette
Bonjour,

Pierre Maurette wrote:

2 - La norme semble indique z comme modificateur de longueur pour des
size_t. Or, seul gcc 3.3 *sous Linux* l'accepte et même le demande. Il
accepte également Z. D'où le cast qui évite partout les warnings. Les
autres affichent %zd, %zu, %z etc. Why ?
%z, c'est pas du C99 par hasard ?

Sans doute. C'est la seule norme dont j'ai un exemplaire complet, et

pas un seul compilateur 100% C99. C'est pas finot, j'en conviens. Le
plus proche est donc gcc 3.3, gcc 3.4 (et 4.0 ?).
Merci...

--
Pierre


Avatar
Jean-Marc Bourguet
"Pierre Maurette" writes:

Bonjour,

Pierre Maurette wrote:

2 - La norme semble indique z comme modificateur de longueur pour des
size_t. Or, seul gcc 3.3 *sous Linux* l'accepte et même le demande. Il
accepte également Z. D'où le cast qui évite partout les warnings. Les
autres affichent %zd, %zu, %z etc. Why ?
%z, c'est pas du C99 par hasard ?

Sans doute.



C'est certain.

C'est la seule norme dont j'ai un exemplaire complet, et pas un seul
compilateur 100% C99. C'est pas finot, j'en conviens. Le plus proche
est donc gcc 3.3, gcc 3.4 (et 4.0 ?). Merci...


C'est plutot une affaire de bibliotheque que de compilateur. Et gcc
se contente de fournir le compilateur (pour le C; pour Ada et C++ il
fournit la bibliotheque standard aussi).

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Antoine Leca
Pierre Maurette wrote:
#define AFF_SIZE(a) printf("sizeof("#a"): %zdn", sizeof(a));


Strictement parlant, ce devrait être %zu.

Quid de celle-ci ? A part qu'elle fait n'importe quoi si
l'argument n'est pas un type valide *au run-time*.


Heu ?
Si tu passes une variable ou une constante, cela semble aller sans trop de
souci, non ?

Évidemment, avec une fonction, c'est autre chose...


2 - La norme semble indique z comme modificateur de longueur pour des
size_t. Or, seul gcc 3.3 *sous Linux* l'accepte et même le demande. Il
accepte également Z. D'où le cast qui évite partout les warnings. Les
autres affichent %zd, %zu, %z etc. Why ?


%zu est C99.
Z serait une extension spécifique à la libc Linux (compatibilité
ascendante). Certaines manpages disent même de l'éviter.


3 - Tous acceptent (en macro ou pas) sizeof(void(*)(void)). Mais gcc
3.3 sous Linux (et Eclipse/CDT que je teste à nouveau) râle.


Silencieux ici (GCC 3.2 ou 3.4.2, C90 ou C99, -W -Wall -pedantic).


Antoine

Avatar
Pierre Maurette
Pierre Maurette wrote:
#define AFF_SIZE(a) printf("sizeof("#a"): %zdn", sizeof(a));


Strictement parlant, ce devrait être %zu.
C'est sûr. J'ai essayé, cf plus bas. Mais ça ne change rien.



%zu est C99.
Z serait une extension spécifique à la libc Linux (compatibilité
ascendante). Certaines manpages disent même de l'éviter.
Oui, je viens de voir un truc comme ça dans Google. Ils disent que le Z

est lié à libc5.



3 - Tous acceptent (en macro ou pas) sizeof(void(*)(void)). Mais gcc
3.3 sous Linux (et Eclipse/CDT que je teste à nouveau) râle.


Silencieux ici (GCC 3.2 ou 3.4.2, C90 ou C99, -W -Wall -pedantic).
gcc est également silencieux chez moi. C'est le truc d'Eclipse qui ne

doit pas être tout à fait terminé.

--
Pierre


Avatar
Emmanuel Delahaye
Pierre Maurette wrote on 26/04/05 :
#define AFF_SIZE(a) printf("sizeof("#a"): %zdn", sizeof(a));


Comportement indéfini. Pour size_t, c'est "%zu". (Je ne suis même pas
sûr que "%zd" existe...

Le reste me parrait correct. On peut améliorer la présentation.

#include"stdio.h"
#include"stdlib.h"

#if 0
#define AFF_SIZE(a)
printf("%-24s: %zun", "sizeof("#a")", sizeof(a))
#else
#define AFF_SIZE(a)
printf("%-24s: %un", "sizeof("#a")", (unsigned)sizeof(a))
#endif

int main (void)
{
typedef void (*fptr) (void);
size_t s1 = sizeof (fptr);
size_t s2 = sizeof (void (*)(void));
printf ("%ut%un", (unsigned) s1, (unsigned) s2);

AFF_SIZE (char);
/* etc. */
AFF_SIZE (void *);
AFF_SIZE (void (*)(void));
AFF_SIZE (fptr);
return 0;
}

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.

Avatar
Antoine Leca
Emmanuel Delahaye wrote:
Je ne suis même pas sûr que "%zd" existe...


Comment pourrais-tu imprimer un ssize_t (Posix, résultat de read(2) par
exemple) sans cela ?



Antoine

Avatar
Pierre Maurette
Pierre Maurette wrote on 26/04/05 :
#define AFF_SIZE(a) printf("sizeof("#a"): %zdn", sizeof(a));


Comportement indéfini. Pour size_t, c'est "%zu". (Je ne suis même pas sûr que
"%zd" existe...
C'est certain, tout aurait du être en unsigned. Pas de discussion

là-dessus, c'est une erreur, j'avais commencé avec un %zd à cause d'une
mauvaise lecture d'un Google (ssize_t).
Ceci étant acquis, il me semble que %zd existe:
<C99: $7.19.6.1.7>
z : Specifies that a following d, i, o, u, x, or X conversion specifier
applies to a size_t or the corresponding signed integer type argument;
or that a following n conversion specifier applies to a pointer to a
signed integer type corresponding to size_t argument.
</C99>
De plus, je pense que si le size_t est inférieur à INT_MAX, le
comportement est défini. Et on est largement dans ce cas, puisque je
mesure des types simples. J'ai quand même un sizeof(long double) de 16,
ce qui est une surprise et sera creusé ... Je vois deux raisons
possibles, d'abord qu'il y ait vraiment en AMD64 des floats sur 128
bits (mais je ne le crois pas), ensuite plus vraisemblablement qu'il
s'agisse de 80 bits avec padding.

Le reste me parrait correct. On peut améliorer la présentation.

#include"stdio.h"
#include"stdlib.h"

#if 0
#define AFF_SIZE(a)
printf("%-24s: %zun", "sizeof("#a")", sizeof(a))
#else
#define AFF_SIZE(a)
printf("%-24s: %un", "sizeof("#a")", (unsigned)sizeof(a))
#endif
OK. Mais dans mon cas, la seconde version suffira dans tous les cas.

En fait, j'avais laissé une ligne commentée pour montrer ce qui ne
passait pas partout, mais je charchais un code unique. Ça prêtait à
confusion.

--
Pierre