2010-06-16 5 views
4

Comme cela est apparent dans le titre, je questionne la raison derrière la définition des macros à l'intérieur d'une structure. Je vois souvent cette approche dans la programmation du réseau, par exemple, suivant extrait:Quelle est la logique derrière la définition de macros dans une structure?

struct sniff_tcp { 
    u_short th_sport;    /* source port */ 
    u_short th_dport;    /* destination port */ 
    tcp_seq th_seq;     /* sequence number */ 
    tcp_seq th_ack;     /* acknowledgement number */ 
    u_char th_offx2;    /* data offset, rsvd */ 
#define TH_OFF(th)  (((th)->th_offx2 & 0xf0) >> 4) 
    u_char th_flags; 
    #define TH_FIN 0x01 
    #define TH_SYN 0x02 
    #define TH_RST 0x04 
    #define TH_PUSH 0x08 
    #define TH_ACK 0x10 
    #define TH_URG 0x20 
    #define TH_ECE 0x40 
    #define TH_CWR 0x80 
    #define TH_FLAGS  (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR) 
    u_short th_win;     /* window */ 
    u_short th_sum;     /* checksum */ 
    u_short th_urp;     /* urgent pointer */ 
}; 

Cet exemple est à partir du code sniffex.c sur le site Web de tcpdump. Est-ce pour améliorer la lisibilité et clarifier le code?

+1

Peut-être que l'auteur d'origine aime revenir après un jour férié et ne pas avoir à regarder des fichiers différents pour se rappeler ce que signifient ces macros. – vpit3833

+1

Si c'est le cas, l'auteur devrait investir dans un éditeur qui supporte ctags. –

+0

gcc dispose également d'une fonctionnalité impressionnante pour l'expansion de macro. (avec l'option -E) – systemsfault

Répondre

1

je pense, ce n'est pas « meilleure pratique », il faut garder les valeurs pour (définit) près de la struct, mais pas à l'intérieur du struct.

(Encore mieux serait de ENUM et typedef les constantes, donc un compilateur peut avertir si pas tapé correctement).

La macro TH_OFF() est un autre cas, où il « se cache » un autre élément, alors peut-être il pourrait être mis à ce poste (avec un commentaire approprié)

+1

+1 pour enum. J'aime utiliser une énumération pour certains champs comme un état, mais je ne pense pas que ce soit approprié pour les bits masqués dans un champ. – tomlogic

+0

'enum' est une mauvaise idée ... en supposant des entiers de 16 bits, comment écrivez-vous une constante d'énumération avec la valeur 0x8000? Ce n'est pas possible. De même, c'est une mauvaise idée d'utiliser des variables signées en arithmétique entière. – Lundin

6

Eh bien, les constantes définies étaient pertinentes pour les valeurs possibles de l'un des champs.

Ainsi, l'auteur a décidé d'améliorer la localité de code, et rendre les utilisateurs de l'API éviter de tourner en rond. Cela semble logique.

Sinon, le préprocesseur est complètement indépendant du code. Vous pouvez même mettre une définition dans une expression.

+3

Ok donc ça n'a pas toute autre fonction. Mais cela m'a paru vraiment bizarre, parce que pour moi, c'est juste compliquer les choses. Je ne trouve pas utile de mettre quelque chose dans une structure que vous ne pouvez pas appeler dans la structure correspondante. Pour moi, si vous voulez une localité de code, vous pouvez simplement la placer au-dessus de la structure. – systemsfault

3

Nous devons croire qu'il est tentant de transmettre nous que les macros doivent seulement être utilisées en conjonction avec des données dans cette structure, mais c'est une manière pauvre et alambiquée de représenter cela.

En C++, il pourrait être préférable d'utiliser un ENUM imbriquée et une fonction en ligne pour ce faire, mais étant donné que le code est une macro C est probablement la meilleure alternative.

À mon avis, il diminue la lisibilité et je préférerais voir les macros en dehors du struct avec des commentaires indiquant où et comment ils doivent être utilisés. De cette façon, il n'y a aucune idée de ce que sont exactement les macros et la définition de structure reste libre de vilain.

1

L'intention de l'auteur semble être que les choses qui appartiennent ensemble doivent être situés ensemble. Ainsi, les macros de drapeau devraient être juste sous le drapeau. Avec la même logique, une définition de macro n'a rien à voir avec une déclaration de structure, donc les macros et non y appartiennent. Il n'y a rien de mal à les mettre juste au-dessus ou au-dessous de la structure.

Je me demande si l'auteur aurait été cohérent et fait la même chose si le drapeau aurait été un u_long avec 32 macros de drapeau et quelques autres supplémentaires macros de combinaison par défaut?

2

une utilisation typique est comme indiqué ci-dessous

comprennent

Supposons que votre première version de foo est un peu comme indiqué ci-dessous.

struct foo1 { 
int x;`enter code here` 
... 
}; 

Et demain vous essayez d'améliorer la structure foo de la manière suivante

struct foo2 { 
union { 
    int x; 
    int y; 
} u; 
#define x u.x 
#define y u.y 
}; 

La déclaration comme ci-dessus ne cassera pas la compilation dans des endroits où vous avez utilisé foo_var.x depuis la nouvelle définition du foo_var.x struct est toujours valide et est rien foo_var.ux

par exemple l'utilisation:

struct foo { 
union { 
    int x; 
    int y; 
} u; 
#define x u.x 
#define y u.y 
}; 

int main() 
{ 
    struct foo f; 

    f.x = 1; 
    f.y = 2; 
} 
+0

c'est un peu différent de l'affaire dans le post. Mais c'est un usage intéressant, merci. – systemsfault

Questions connexes