2009-05-26 2 views
9

Мне нужно передать пакеты через Интернет, длина которых должна быть динамической.C: Рекомендуемый стиль для динамически размерных структур

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

Проблема в том, что массивы нулевой длины не соответствуют требованиям ISO.

Вместо этого следует использовать char filename[1];? Но тогда sizeof(struct packet) больше не вернет правильное значение.

ответ

6

Classic выпуск. Вы можете просто справиться с этим (и обратите внимание, что sizeof (foo) может быть выключен более чем одним, если компилятор округляет размер структуры, что (я считаю) разрешено), или вы можете сделать что-то вроде этого:

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

Это раздражает (вы должны использовать h.id и т. Д.), Но он работает. Обычно я просто разбираюсь в том, что он один, но вышеупомянутое может быть немного более портативным.

6

Думаю, вам следует посмотреть на некоторые существующие примеры структур с динамическим размером для руководства здесь. Лучший пример, который я знаю, - это TOKEN API в Win32. Они используют макрос ANYSIZE_ARRAY, который просто решает до 1. Raymond Chen сделал обширный блог статью с подробным описанием, почему именно они сделаны таким образом

Что касается таких операций, как SizeOf неудачи. Это не сработает независимо от того, какое решение вы выбрали для структуры с динамическим размером. sizeof - это операция времени компиляции, и вы будете перенастраивать структуру во время выполнения. Он просто не может работать.

+0

с sizeof Я имел в виду только размер структуры, а не динамическое поле, потому что при приеме UDP-пакета я сначала читал в структуре, которая содержит размер динамического поля, а затем я читаю динамическое поле. – codymanix

4

Предлагаю использовать char filename[1] и включать завершающий 0-байтовый. Таким образом, вы можете malloc() правильный размер структуры и избежать ошибок, одноразовые, как это:

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

Но приемник должен знать, что он должен прочитать filename_len+1 байт.

3

Действительно zero-length arrays не входят в стандарт. Но то, что у вас есть в фрагменте кода, представляет собой гибкий массив, который является частью стандарта ISO C99. Если вы можете использовать C99, я бы использовал гибкий массив, если предложение jesup, пожалуй, самое лучшее.

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