2009-05-26 10 views
9

Potrzebuję przesyłać pakiety przez Internet, których długość powinna być dynamiczna.C: Zalecany styl dla dynamicznie sortowanych struktur

struct packet 
{ 
    int id; 
    int filename_len; 
    char filename[]; 
}; 

Problem polega na tym, że macierze o zerowej długości nie są zgodne z normą ISO.

Czy należy zamiast tego używać char filename[1];? Ale wtedy sizeof(struct packet) nie zwróci poprawnej wartości.

Odpowiedz

6

Klasyczny numer. Możesz po prostu sobie z tym poradzić (i zauważ, że sizeof (foo) może być wyłączony o więcej niż jeden, jeśli kompilator zaokrągla rozmiar struktury, co jest dozwolone (wierzę), lub możesz zrobić coś takiego:

struct packetheader { 
    int id; 
    int filename_len; 
}; 
struct packet { 
    struct packetheader h; 
    char filename[1]; 
}; 

To jest denerwujące (musisz użyć h.id, itp.), Ale działa. Zazwyczaj po prostu sobie z tym poradzę, ale powyższe może być nieco bardziej przenośne.

6

Myślę, że powinieneś przyjrzeć się istniejącym przykładom struktur o dynamicznym rozmiarze w celu uzyskania wskazówek. Najlepszym przykładem, jaki znam, są API TOKEN w Win32. Używają makro ANYSIZE_ARRAY który właśnie rozwiązuje aż do 1. Raymond Chen zrobił obszerny wpis na blogu szczegółowo, dlaczego są one wykonane w ten sposób

Jak dla operacji takich jak sizeof niepowodzeniem. To nie powiedzie się bez względu na to, jakie rozwiązanie wybierzesz dla dynamicznie sortowanej struktury. sizeof to operacja czasu kompilacji, a ty zmienisz strukturę w czasie wykonywania. Po prostu nie może działać.

+0

z sizeof Mam na myśli tylko rozmiar struktury, a nie pole dynamiczne, ponieważ podczas odbierania pakietu UDP najpierw czytałem w strukturze zawierającej rozmiar pola dynamicznego, a następnie czytałem pole dynamiczne. – codymanix

4

Proponuję użyć char filename[1] i dołączyć 0-bajt kończący. W ten sposób można malloc() prawidłowy rozmiar struktury i uniknąć błędów jednorazowych tak:

ptr = malloc(sizeof(struct packet)+filename_len); 
strncpy(&ptr->filename, filename, filename_len); 

Ale odbiornik musi wiedzieć, że to musi przeczytać filename_len+1 bajtów.

3

Rzeczywiście zero-length arrays nie są częścią standardu. Ale to, co masz w swoim fragmencie kodu, jest elastyczną tablicą, która jest częścią standardu ISO C99. Jeśli możesz używać C99, używałbym elastycznej tablicy, jeśli nie sugestia jesup jest prawdopodobnie najlepsza.