2010-06-16 3 views
4

Как видно в заголовке, я задаюсь вопросом о причине определения макросов внутри структуры. Я часто вижу этот подход в сетевом программировании, например, следующий фрагмент кода:Какова логика определения макросов внутри структуры?

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 */ 
}; 

Этот пример из sniffex.c кода в веб-сайте TCPDUMP в.

Это улучшает читаемость и делает код более четким.

+1

Возможно, оригинальному автору нравится возвращаться после праздника и не нужно смотреть на разные файлы, чтобы вспомнить, что означают эти макросы. – vpit3833

+1

Если это так, автор должен инвестировать в редактор, который поддерживает ctags. –

+0

Также gcc обладает потрясающей функциональностью для расширения макросов. (с опцией -E) – systemsfault

ответ

1

Я думаю, что это не «лучшая практика», следует хранить определения (для значений) возле структуры, но не внутри структуры.

(Еще лучше было бы перечислять и вводить константы, поэтому компилятор мог бы предупредить, если не набрал правильно).

TH_OFF() макрос еще один случай, когда он «скрывает» еще один элемент, поэтому, возможно, можно было бы поставить в этой позиции (с соответствующим комментарием)

+1

+1 для перечисления. Мне нравится использовать перечисление для некоторых полей, таких как состояние, но я не думаю, что это подходит для замаскированных бит в поле. – tomlogic

+0

'enum' - плохая идея ... предполагая 16-битные целые числа, как вы пишете константу перечисления со значением 0x8000? Это невозможно. Точно так же плохой идеей использовать подписанные переменные в целочисленной арифметике. – Lundin

6

Ну, определенные константы были релевантны возможным значениям одного из полей.

Итак, автор решил улучшить местонахождение кода и заставить пользователей API избегать использования в кругах. Кажется логичным.

В противном случае препроцессор полностью не зависит от кода. Вы даже можете задать определение внутри выражения.

+3

Итак, у него нет любая другая функция. Но это выглядело очень странно для меня, потому что для меня это просто усложняет ситуацию. Я не считаю целесообразным помещать что-то внутри структуры, которую вы не можете назвать в соответствующей структуре. Для меня, если вам нужна локальность кода, вы можете просто положить его над структурой. – systemsfault

3

У нас есть подозрение, что он пытается передать что макросы должны использоваться только совместно с данными в этой структуре, но это плохой и запутанный способ представить это.

В C++ может быть предпочтительнее использовать вложенное перечисление и встроенную функцию для выполнения этого, но поскольку код C, макрос, вероятно, является лучшей альтернативой.

По-моему, это уменьшает читаемость, и я предпочел бы видеть макросы вне структуры с комментариями, указывающими, где и как их следует использовать. Таким образом, нет никаких догадок относительно того, для чего предназначены макросы, и определение структуры остается свободным от трещин.

1

Целью автора является то, что вещи, которые принадлежат друг другу, должны быть расположены вместе. Таким образом, макросы флагов должны быть под флагом. С той же логикой определение макроса не имеет ничего общего с объявлением структуры, поэтому макросы имеют , а не. Нет ничего плохого в том, чтобы поставить их выше или ниже структуры.

Интересно, был ли автор последовательным и проделанным то же самое, если бы флаг был u_long с 32 флаговыми макросами и еще несколькими дополнительными макросами по умолчанию?

2

один типичный вариант использования является, как показано ниже

включают

Предположим, что ваша первая версия обув несколько, как показано ниже.

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

А завтра вы пытаетесь улучшить структуру Foo следующим образом

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

Декларация, как это делалось выше, не будет нарушать компиляцию в тех местах, где у вас есть используется foo_var.x, поскольку с новым определение структуры foo_var.x остается в силе и не ничего, кроме foo_var.ux

например использование:

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

что-то отличное от случая в сообщении. Но это интересное использование, спасибо. – systemsfault

Смежные вопросы