2013-07-18 3 views
0

Я нашел его в каком-то внешнем коде, он выглядит несколько проблем, но код работает нормально, вы можете помочь, если этот фрагмент кода имеет какие-то вещи.Размер упакованной структуры в C, это правильно?

почему игнорировать два без знака при вычислении размера структуры ?

 tmsg_sz = sizeof(plfm_xml_header_t) + sizeof(oid_t) + sizeof(char*) 
      + sizeof(unsigned) + sizeof(snmp_varbind_t)*5 ; 
     tmsg = (snmp_trap_t*) malloc(tmsg_sz); 
     if (!tmsg) { 
      PRINTF("malloc failed \n"); 
      free(trap_msg); 
      return -1; 
     } 
     memset (tmsg, 0, tmsg_sz); 
     tmsg->hdr.type = PLFM_SNMPTRAP_MSG; 
     copy_oid_oidt(clog_msg_gen_notif_oid, OID_LENGTH(clog_msg_gen_notif_oid), &tmsg->oid); 
     tmsg->trap_type = SNMP_TRAP_ENTERPRISESPECIFIC; 
     tmsg->trap_specific = 1; 
     tmsg->trapmsg = strdup("Trap Message"); 
     tmsg->numofvar = 5; 
     build_snmp_varbind(&(tmsg->vars[0]), facility, STR_DATA_TYPE, sizeof(facility)+1, clog_hist_facility_oid, 14); 

     build_snmp_varbind(&(tmsg->vars[1]), &sev, U32_DATA_TYPE, sizeof(sev),clog_hist_severity_oid, 14); 

     build_snmp_varbind(&(tmsg->vars[2]), name, STR_DATA_TYPE, sizeof(name)+1, clog_hist_msgname_oid, 14); 

     build_snmp_varbind(&(tmsg->vars[3]), trap_msg, STR_DATA_TYPE, strlen(trap_msg)+1,clog_hist_msgtext_oid, 14); 

     // get system uptime 
     long uptime = get_uptime(); 
     build_snmp_varbind(&(tmsg->vars[4]), (long*)&uptime, TMR_DATA_TYPE, sizeof(uptime),clog_hist_timestamp_oid, 14); 



    typedef struct snmp_trap_s { 
     plfm_xml_header_t hdr; 
     oid_t    oid;  /* trap oid */ 
     unsigned   trap_type; 
     unsigned   trap_specific; 
     char    *trapmsg; /* text message for this trap */ 
     unsigned   numofvar; 
     snmp_varbind_t vars[0]; 
    } __attribute__((__packed__)) snmp_trap_t; 
+0

«Почему игнорировать два без знака при вычислении размера структуры?» А? –

+0

@Judeyou Это один из способов упаковать структуру данных. Похоже, это для gcc. Например, другие компиляторы используют #pragma pack (1). Как вы думаете, что здесь неправильно? –

+0

Это выглядит странно для меня. Я бы подумал, что размер был бы рассчитан как 'sizeof (snmp_trap_s)'. – STLDeveloper

ответ

0

Компиляторы стараются поместить многобайтовые данные, выровненные по-разному. Например, переменная int, в архитектуре, где sizeof int == 4, может потребоваться разместить в месте, делящемся на 4. Это может быть трудным требованием, или это может сделать систему более эффективной; это зависит от компьютера. Итак, рассмотрим

typedef struct combo { 
    char c; 
    int i; 
} combo; 

В зависимости от архитектуры, sizeof combo может быть 5, 6, или чаще всего 8. Замена двух членов, и размер должен быть 5.

typedef struct combo2 { 
    int i; 
    char c; 
} combo2; 

Однако массив из combo2 s могут иметь размер не ожидаю:

combo2 cb[2]; 

размера cb вполне может быть 16, а 3 байта неиспользуемого пространства следует combo2[0] и combo2[1]. Это позволяет combo2[1].i начать с места, делящегося на 4.

Рекомендация состоит в том, чтобы заказать элементы структуры по размеру; 8-байтовые члены должны предшествовать 4-байтовым членам, затем 2-байтовые члены, а затем 1-байтовые члены. Конечно, вы должны знать о типичных размерах, и вы не можете работать над нечеткой архитектурой, где символы не упаковываются в более крупные слова. Cray? кашель-кашель.

+0

@Peter L. Я имею в виду размер структуры, почему 2 unsigned могут быть опущены при вычислении. – Judeyou