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

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

10 réponses

1 2 3 4
Avatar
Pierre Maurette
On 8 juin, 08:29, Pierre Maurette wrote:
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;


Un commentaire en passant, je trouve que c'est une tres mauvaise
pratique de faire un typedef d'un tableau, meme de taille fixe. La
semantique de passage par valeur "naturelle" devient une semantique
par reference sans prevenir. De plus tu ne pourra pas retourner des
variables de ce type. Pourquoi ne pas mettre les tableaux dans des
structures?


Je n'avais répondu qu'à la dernière phrase. Je viens de relire plus
attentivement. Effectivement, il y a techniquement un inconvénient à
typedef-er un tableau, et un tableau de taille unité plus encore, parce
que plus confusant.
Je ne pense pas qu'il y ait un risque réel de bug insidieux, vu que le
retour du type est rejeté à la compilation, et que l'accès au type
passé en paramètre doit être indicé. Il faut quand même se méfier d'un
refactoring du type d'entier vers tableau de taille unité, avec ajout
"mécanique" des indices. Le problème serait plutôt de partir sur une
idée de fonction erronée et de revenir - rapidement - en arrière.
Le contexte veut que je commence à coder et à valider des parties avant
que l'analyse ne soit aboutie. J'ai pour l'instant besoin de types de
sizeof 1, 3 et 4 rapidement interchangeables (avant compilation). D'où
pour l'instant les deux étages de typedef.

--
Pierre Maurette


Avatar
Denis Leger
Le Fri, 08 Jun 2007 21:27:26 +0200

J'aurais aimé quelque chose d'utile, genre règle de nommage pour les
types typedef-és malgré l'opposition de l'Enseignant. C'est pourtant
ici que j'avais appris que le suffixage par _t était *très* mal.


Pourquoi est-ce très mal ?

--
Denis Léger (embêté car j'utilise toujours cette notation... que je
trouve commode)

Avatar
espie
In article ,
Denis Leger wrote:
Le Fri, 08 Jun 2007 21:27:26 +0200

J'aurais aimé quelque chose d'utile, genre règle de nommage pour les
types typedef-és malgré l'opposition de l'Enseignant. C'est pourtant
ici que j'avais appris que le suffixage par _t était *très* mal.


Pourquoi est-ce très mal ?



Denis Léger (embêté car j'utilise toujours cette notation... que je
trouve commode)


*_t est reserve par la norme, pour l'utilisation du systeme.
Comme deux trois autres choses:
- les noms de fonction en str*
- les macros en E[A-Z]*

Je n'ai pas les noms exacts reserves en tete, cote minuscules et majuscules,
mais il faut bien voir que ce ne sont pas juste quelques noms, comme size_t
ou strcpy, qui sont reserves par le systeme, mais bien la totalite d'un
espace de nom.

Ca veut dire que, par exemple, si tu definis un typedef foo_t dans ton code,
ce code devient non portable: un systeme quelconque peut tres bien avoir
un typedef foo_t dans ses entetes... meme si foo_t n'est pas dans la norme
C99, c'est pas grave: c'est le systeme en question qui a raison, la norme
lui a octroye TOUT l'espace de noms *_t pour ses typedefs.

On rencontre souvent des *_t dans du code utilisateur. Pourquoi donc:
- pas mal de gens programment par mimetisme. Ils ont vu l'utilisation de
typedef xxx foo_t dans du code systeme, et ca leur a paru joli comme
notation.
- il regne souvent une certaine confusion entre ce qui est `code systeme'
et `code utilisateur'. Certains projects considerent que leurs bibliotheques
font partie du systeme, et s'octroient donc le droit de definir des
typedef... ils le font parfois en connaissance de cause, a savoir que ca
rend les choses un peu plus complexes a porter, voire cauchemardesques
(je pense entre autres a une grosse partie du projet GNU, relativement
schizophrene, du cote de gettext, glib, et iconv, qui ne sait pas trop
si elle fait partie du systeme, ou pas... avec une volonte politique plus
ou moins affirmee et plus ou moins coherente de definir la `suite' de
la norme.

Il faut voir aussi que pas mal de code utilise actuellement est relativement
ancien... en particulier, quand on regarde les contorsions faites par
certaines bibliotheques pour etre portable, il faut bien realiser qu'il
y a des bouts la-dedans qui n'ont pas bouge d'un poil depuis dix a quinze
ans (et c'est parfaitement normal: ces bouts s'adressent a des systemes
du meme age, tournent sur ceux-ci, et ca n'apporterait pas grand chose
de les moderniser, a part peut-etre casser les systemes en question).

C'est sur que, avec des noms de typedef judicieusement choisis, le risque
de collision avec le systeme est faible... mais bon, pourquoi tenter
le diable ? la quasi-totalite des noms d'objets ne sont *pas* reserves
par la norme, alors pourquoi utiliser expres ceux qui sont interdits ?


Avatar
Denis Leger
Le Sat, 9 Jun 2007 11:32:58 +0000 (UTC)

In article ,
Denis Leger wrote:
Le Fri, 08 Jun 2007 21:27:26 +0200

J'aurais aimé quelque chose d'utile, genre règle de nommage pour
les types typedef-és malgré l'opposition de l'Enseignant. C'est
pourtant ici que j'avais appris que le suffixage par _t était
*très* mal.


Pourquoi est-ce très mal ?



[...]

On rencontre souvent des *_t dans du code utilisateur. Pourquoi donc:
- pas mal de gens programment par mimetisme. Ils ont vu l'utilisation
de typedef xxx foo_t dans du code systeme, et ca leur a paru joli
comme notation.


Ben oui, on apprend souvent à programmer par mimétisme...

J'ai en tout cas compris le problème, puis-je à l'évenir utiliser sans
souci t_montype plutôt que montype_t ? Ou y a-t-il une convention de
nommage précise ?

Amicalement,

--
Denis Léger
MP Maths -- Brest



Avatar
espie
In article ,
Denis Leger wrote:
J'ai en tout cas compris le problème, puis-je à l'évenir utiliser sans
souci t_montype plutôt que montype_t ? Ou y a-t-il une convention de
nommage précise ?


Oui, sans probleme. Ca ne rentre pas en collision avec la norme.

Je ne connais pas de convention de nommage "universelle".

Avatar
Denis Leger
Le Sat, 9 Jun 2007 19:40:28 +0000 (UTC)

In article ,
Denis Leger wrote:
J'ai en tout cas compris le problème, puis-je à l'évenir utiliser
sans souci t_montype plutôt que montype_t ? Ou y a-t-il une
convention de nommage précise ?


Oui, sans probleme. Ca ne rentre pas en collision avec la norme.

Je ne connais pas de convention de nommage "universelle".


Merci pour ces précisions.

--
Denis Léger
MP Maths -- Brest


Avatar
Marc Boyer
Le 08-06-2007, Thierry B a écrit :
--{ Marc Boyer a plopé ceci: }--

Un commentaire sur le commentaire. Lorsque j'enseigne le C, je deconseille
toujours l'usage de typedef et l'usage de macros (*) aux debutants.

*: pour autre chose que de betes #define VALUE 42


Même un typedef sur des structs ?


Si, pour moi, celui-ci peut être bien, et même souvent,
comment dire, "clarifiant", à condition que le nom soit
bien choisi.


C'est aussi mon sentiment, et ça semble idiomatique. Mais
Marc Espie semblait émettre des réserves.

Et _surtout_, de ne pas passer à la déclaration
d'un typedef pour les pointeurs sur la structure "typedéfée"
à l'étape précedente. Pour moi, un pointeur doit *toujours*
rester explicite. Bon, je ne suis pas une référence non
plus, c'est juste que je fonctionne comme ça :-(


A mon sens, si on fait un typedef, c'est pour définir un nouveau
type, un nouvel usage. En effet, si on a juste besoin d'un pointeur,
je conseillerais de faire une struc avec un unique pointeur dedans.

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
Thierry B
--{ Marc Boyer a plopé ceci: }--

*: pour autre chose que de betes #define VALUE 42


Même un typedef sur des structs ?


Si, pour moi, celui-ci peut être bien, et même souvent,
comment dire, "clarifiant", à condition que le nom soit
bien choisi.


C'est aussi mon sentiment, et ça semble idiomatique. Mais
Marc Espie semblait émettre des réserves.

Oui, j'ai vu. Il faut bien entendu que le nom soit bien choisi,

et là, c'est affaire de conventions personnelles (dans mon cas)
ou de règles clairement prédéfinies dans le cas d'un projet.
Il me semble bien qu'à la lecture de ce nom, il soit immédiat
de se dire "c'est un typedef pour ce projet/cette lib".

Et _surtout_, de ne pas passer à la déclaration
d'un typedef pour les pointeurs sur la structure "typedéfée"
à l'étape précedente. Pour moi, un pointeur doit *toujours*
rester explicite. Bon, je ne suis pas une référence non
plus, c'est juste que je fonctionne comme ça :-(


A mon sens, si on fait un typedef, c'est pour définir un nouveau
type, un nouvel usage. En effet, si on a juste besoin d'un pointeur,
je conseillerais de faire une struc avec un unique pointeur dedans.


Euh ? mettre un unique pointeur dans une structure, j'ai du mal
à voir, un petit exemple ? En fait ce que je voulais dire, c'est
(/me réfléchit...)(/me écrit un exemple)... Voilà:

#v+
/* exemple rapide */
#define T_NOM 42
typedef struct
{
char nom[T_NOM+1];
int valeur;
} Mon_Machin;
typedef Mon_Machin *Mon_Machin_Ptr; /* <----- ici */
int main(int argc, char *argv[])
{
Mon_Machin machin;
Mon_Machin_Ptr truc; /* <----- et la */
machin.valeur = 51;
truc = &machin;
return 0;
}
#v-

C'est ce genre de typedef que je n'aime pas, puisque plus loin dans
le code, il n'est pas immédiat que c'est réellement un pointeur C,
l'interprétation est plus "subjective".

En espérant avoir été un peu plus clair sur ma pensée.


--
Le linuxien est bolchévique par définition. Il mange donc les enfants.
CQFD.
--{ Oxxxxxx, in f.m.b.l + Faut assumer }--




Avatar
Pierre Maurette
Le 08-06-2007, Thierry B a écrit :
--{ Marc Boyer a plopé ceci: }--



[...]

Si, pour moi, celui-ci peut être bien, et même souvent,
comment dire, "clarifiant", à condition que le nom soit
bien choisi.


C'est aussi mon sentiment, et ça semble idiomatique.


J'ai constaté que je finissais par admettre la pertinence de
pratiquement toutes les "règles de puriste". La défiance absolue envers
le typedef fait exception, y compris le typedef de pointeur. A moins
que ce ne soit pas vraiment une règle de puriste.
Par exemple un objet qui est fondamentale un pointeur, c'est à dire que
à priori l'application ne le déréférencera pas. J'ai en tête une liste
(par langue) de listes de mots (de const char*). On arrivera donc sans
pour cela que l'analyse soit pourrie à un const char***. Avec le
premier '*' n'entrant à mon sens pas dans la hiérarchie des deux
autres. Le typedef du const char* va alléger tout ça. Et accessoirement
permettre des déclarations sur la même ligne si on aime (quoi que les
puristes...).

[...]

A mon sens, si on fait un typedef, c'est pour définir un nouveau
type, un nouvel usage.


Quand j'ai appris le C, j'avais l'habitude de faire de petits
programmes d'illustration de chaque nouvelle notion. Comme quelqu'un
qui préparerait un cours, mais dans mon cas il s'agissait surtout de
nettoyer le bout de test et de l'archiver, pour ne pas errer à chaque
fois sur le même problème.
Un jour, je me penche sur le typedef. "Le typedef définit un nouveau
type...". OK, j'ai compris:

typedef unsigned age_t;
typedef unsigned categ_t;
/* ... */
age_t x = 49;
categ_t y = 0;
/* ... */
x = y;

Pour montrer l'utilité du warning que j'attends toujours.
Bon, ça montre au moins qu'il est stupide de se priver de la facilité
offerte par un bon nommage. A propos de x et y, pour le xxxx_t je sais
aujourd'hui qu'il ne faut pas.

--
Pierre Maurette


Avatar
Marc Boyer
Le 11-06-2007, Pierre Maurette a écrit :
Le 08-06-2007, Thierry B a écrit :
--{ Marc Boyer a plopé ceci: }--



[...]

Si, pour moi, celui-ci peut être bien, et même souvent,
comment dire, "clarifiant", à condition que le nom soit
bien choisi.


C'est aussi mon sentiment, et ça semble idiomatique.


J'ai constaté que je finissais par admettre la pertinence de
pratiquement toutes les "règles de puriste". La défiance absolue envers
le typedef fait exception, y compris le typedef de pointeur. A moins
que ce ne soit pas vraiment une règle de puriste.
Par exemple un objet qui est fondamentale un pointeur, c'est à dire que
à priori l'application ne le déréférencera pas.


C'est le 'a priori' qui est trompeur.
Programmer en C, c'est aussi se prémunir de sa propre bétise.

J'ai en tête une liste
(par langue) de listes de mots (de const char*). On arrivera donc sans
pour cela que l'analyse soit pourrie à un const char***.
Avec le
premier '*' n'entrant à mon sens pas dans la hiérarchie des deux
autres. Le typedef du const char* va alléger tout ça. Et accessoirement
permettre des déclarations sur la même ligne si on aime (quoi que les
puristes...).


Là, on touche à un autre pb: il manque d'un type 'chaine de caractère'
en C. Mais je ne vois pas ce qu'on va gagner entre
const char*** maliste;
ou
typedef const char* const_string;
const_string** ma_liste;
ou disons que je trouve qu'on gagne peu, et on rend le code non
idiomatique.

A mon sens, si on fait un typedef, c'est pour définir un nouveau
type, un nouvel usage.


Quand j'ai appris le C, j'avais l'habitude de faire de petits
programmes d'illustration de chaque nouvelle notion. Comme quelqu'un
qui préparerait un cours, mais dans mon cas il s'agissait surtout de
nettoyer le bout de test et de l'archiver, pour ne pas errer à chaque
fois sur le même problème.
Un jour, je me penche sur le typedef. "Le typedef définit un nouveau
type...". OK, j'ai compris:

typedef unsigned age_t;
typedef unsigned categ_t;
/* ... */
age_t x = 49;
categ_t y = 0;
/* ... */
x = y;

Pour montrer l'utilité du warning que j'attends toujours.


Ben oui, donc le typedef est inutile... Et le jour où quelqu'un
transforme l'age_t en non-signé, d'autres problèmes arrives.

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