OVH Cloud OVH Cloud

sizeof d'un tableau typedef-é

35 réponses
Avatar
Pierre Maurette
Bonjour,

A partir de ça:

typedef uint8_t pixelRGBA_word[4];
typedef uint8_t pixelRGB_word[3];
typedef uint8_t pixelNG_word[1];

typedef pixelNG_word pixel_word;

je voulais avoir automatiquement le sizeof de ma donnée de type
pixel_word. Sur Google, j'ai dû mal chercher, je tombe uniquement sur
des trucs bateaux concernant les tableaux une fois passés à une
fonction.

Après avoir constaté qu'évidemment il me suffisait de créer un
pixel_word bidon là ou je voulais le sizeof, puis passé du bidon au
temporaire, j'ai de fil en aiguille trouvé ça à mettre dans le .h qui
fonctionne (gcc 3.4):

static const size_t MPI_MUL = sizeof(pixel_word){};
ou
#define MPI_MUL (sizeof(pixel_word){})

Est-ce la bonne pratique ?

Merci et bonne journée...

--
Pierre Maurette

5 réponses

1 2 3 4
Avatar
JKB
Le 12-06-2007, à propos de
[HS] Re: sizeof d'un tableau typedef-é,
Thierry B écrivait dans fr.comp.lang.c :
--{ Marc Boyer a plopé ceci: }--

Programmer en C, c'est aussi se prémunir de sa propre bétise.


Ah ben ça oui...

Thierry, coredumpeur professionnel.


Pourtant, on guérit ça très bien...

rayleigh:[~/bin] > ulimit -c 0

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.


Avatar
Marc Boyer
Le 12-06-2007, Marc Espie a écrit :
Lorsque je vois une fonction de prototype:
void f(struct machin *a);

je sais ce que la fonction prend comme parametre, et a quoi je peux
m'attendre comme semantique.

Lorsque je vois une fonction de prototype
void f(machin a);

eh bien, je ne sais pas si machin est un type scalaire, un type pointeur
(de quel niveau ?) ou autre chose. Faudra que j'aille chercher sa definition
pour comprendre ce qui se passe, meme au niveau syntaxique.


Je ne vois pas de réelle différence. D'abord, comparons ce qui
est comparable:
void f(struct machin a);
void g(machin a);

Ah, je me dis, f ne modifie pas 'a', alors que 'g', on sait pas.
Ben non

struct machin {
int* values;
size_t size;
};
void f(struct machin a){
for(unsigned i=0 ; i < a.size ; ++i)
values[i]= 0;
}

De même, un "unsigned" peut etre utilisé 'classiquement', mais il
peut aussi etre une référence/handle sur un objet, et une fonction
void f(unsigned x);
peut en fait aller modifier le truc désigné par x.

De même,
void f(int* x)
ne permet pas de savoir si on passe un unique entier ou un tableau.

Le langage C ne permet pas de préciser la sémantique d'un
sous-programme avec sa seule signature. Après, il y a des
'conventions': * pour mode in/out, pas de typedef sur les
tableaux, etc.

Après, quasiment chaque construction du langage C peut
etre mal utilisée, et le typedef comme les autres.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)

Avatar
Antoine Leca
En news:466f92e5$0$27398$, Harpo va escriure:
On Wed, 13 Jun 2007 06:39:00 +0000, Marc Boyer wrote:

De même, un "unsigned" peut etre utilisé 'classiquement', mais il
peut aussi etre une référence/handle sur un objet, et une fonction
void f(unsigned x);
peut en fait aller modifier le truc désigné par x.


Petit apparté :
Pour cela il est sans doute préférable d'utiliser un 'unsigned long'
pour être plus portable, des archi 64 bits ayant un 'int' de 32 bits.


Toujours en apparté : pour te faire la vie impossible, le fabriquant d'un OS
64 bits appelé à être très répandu (et dont nous tairons le nom par pudeur)
a décidé que sur son OS, les long resteraient sur 32 bits (pour être plus
portable, semble-t-il) tandis que les références, si cela est implémenté
comme des pointeurs, passent elles sur 64 bits :-))))


Sinon, et je suis d'accord avec le fond de ce que veux dire Harpo, c'est une
mauvaise idée en C de faire des suppositions comme celle de MarcB ci-dessus,
c'est une source sans fin de problèmes lors des portages.
D'abord, la logique du C mène à utiliser des 'int' pour des choses comme les
références ou les handles (cf. Kernighan et Ritchie) ; et cf. la remarque de
MarcE qui accepte les typages « sémantiques » genre gid_t ou inode_t.
Ensuite, essayer de façon plus ou moins détournée de « réutiliser » le
contenu de la référence/handle pour être en fait des pointeurs ou à tout le
moins des indices dans un tableau, donc utiliser 'unsigned', va susciter un
jour ou un autre des volontés de meurtre de la part des personnes chargées
des portages vers de nouvelles architectures.
Et c'est tout le point (appuyé par l'expérience, semble-t-il), de Marc
Espie.


Antoine


Avatar
Antoine Leca
En news:4674da7c$0$5086$,
Harpo va escriure:

Par exemple, dans ruby.h (langage Ruby), je vois :

#if SIZEOF_LONG != SIZEOF_VOIDP
# error --->> ruby requires sizeof(void*) == sizeof(long) to
be compiled. <<---
#endif

Les SIZEOF_* étant générés à l'étape de config.

Je ne pense pas que cela limite la portabilité, car il pourrait
très probablement compiler et tourner sur ton archi ci-dessus
moyennant
des modifications à l'étape de config s'il y a quelque chose comme un
int64_t de défini. Mais il semble que jusqu'à présent le besoin ne
s'en soit pas fait sentir.


http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/149545
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/149645
(26-27 juillet 2005)


Antoine

Avatar
Marc Boyer
Le 15-06-2007, Antoine Leca a écrit :
En news:466f92e5$0$27398$, Harpo va escriure:
On Wed, 13 Jun 2007 06:39:00 +0000, Marc Boyer wrote:

De même, un "unsigned" peut etre utilisé 'classiquement', mais il
peut aussi etre une référence/handle sur un objet, et une fonction
void f(unsigned x);
peut en fait aller modifier le truc désigné par x.


Petit apparté :
Pour cela il est sans doute préférable d'utiliser un 'unsigned long'
pour être plus portable, des archi 64 bits ayant un 'int' de 32 bits.


Toujours en apparté : pour te faire la vie impossible, le fabriquant d'un OS
64 bits appelé à être très répandu (et dont nous tairons le nom par pudeur)
a décidé que sur son OS, les long resteraient sur 32 bits (pour être plus
portable, semble-t-il) tandis que les références, si cela est implémenté
comme des pointeurs, passent elles sur 64 bits :-))))

Sinon, et je suis d'accord avec le fond de ce que veux dire Harpo, c'est une
mauvaise idée en C de faire des suppositions comme celle de MarcB ci-dessus,
c'est une source sans fin de problèmes lors des portages.


Je précise peut-être ma pensée: je ne défend pas ce genre d'usage
(loin de là). Je voulais juste souligner que regarder uniquement les
types des paramètres ne dit pas grand chose de la sémantique d'un sous
programme, et qu'interdire l'usage des typedef n'évite en rien les
problèmes.

D'abord, la logique du C mène à utiliser des 'int' pour des choses comme les
références ou les handles (cf. Kernighan et Ritchie) ; et cf. la remarque de
MarcE qui accepte les typages « sémantiques » genre gid_t ou inode_t.


Sauf qu'il les laisse à l'usage de la portabilité et non de la
sémantique.

Ensuite, essayer de façon plus ou moins détournée de « réutiliser » le
contenu de la référence/handle pour être en fait des pointeurs ou à tout le
moins des indices dans un tableau, donc utiliser 'unsigned', va susciter un
jour ou un autre des volontés de meurtre de la part des personnes chargées
des portages vers de nouvelles architectures.


Ca me semble en effet un idée étrange. Mais je l'ai piqué à l'API d'un
OS fameux qui manipule des Handle de tout et de rien...

J'aurais pour ma part tendance à utiliser un struct avec
éventuellement un unique champs, ou une construction type TAD, où l'on
file un pointeur sur struct sans rien dire de ce qu'il y a dedans
(sachant qu'on pourrait justement y mettre rien...).

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)



1 2 3 4