Изменение размера char [x] до char [y] во время выполнения - PullRequest
3 голосов
/ 20 июля 2009

ОК, надеюсь, я правильно объясню. У меня есть структура:

typedef struct _MyData
{
   char Data[256];
   int  Index;
} MyData;

Теперь я столкнулся с проблемой. Большую часть времени MyData.Data работает с 256, но в некоторых случаях мне нужно увеличить количество символов, которые оно может содержать, до разных размеров. Я не могу использовать указатель. Есть ли способ изменить размер данных во время выполнения? Как? Код приветствуется.

Спасибо

EDIT:

Хотя я очень благодарен за все комментарии, комментарии «возможно, попробуйте это ...» или «сделайте это», или «что вы делаете неправильно ...» не помогают. код здесь помощь Пожалуйста, если вы знаете ответ, отправьте код.

и

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

извините за грубость, но я задал вопрос здесь, потому что я уже попробовал все разные подходы, которые, как мне казалось, могли бы работать. Опять же, я ищу код. На данный момент меня не интересуют слова "может сработать ..." или "вы обдумали это ..."

еще раз спасибо и мои извинения

РЕДАКТИРОВАТЬ 2

Почему был задан ответ?

Ответы [ 11 ]

18 голосов
/ 20 июля 2009

Вы можете использовать член гибкого массива

typedef struct _MyData
{
   int  Index;
   char Data[];
} MyData;

Чтобы вы могли выделить необходимое количество места

MyData *d = malloc(sizeof *d + sizeof(char[100]));
d->Data[0..99] = ...;

Позже вы можете освободить и выделить другой кусок памяти и указать на него указатель MyData, и в этот момент у вас будет больше / меньше элементов в элементе гибкого массива (realloc). Обратите внимание, что вам также придется где-то сохранить длину.

Во времена до C99 не было элемента гибкого массива: char Data[] просто рассматривается как массив с неполным типом, и компилятор будет стонать об этом. Здесь я рекомендую вам два возможных выхода

  • Используя указатель: char *Data и сделайте так, чтобы он указывал на выделенную память. Это будет не так удобно, как использование встроенного массива, поскольку вам, возможно, понадобится два выделения: одно для структуры и одно для памяти, на которую указывает указатель. Вместо этого вы также можете разместить структуру в стеке, если ситуация в вашей программе позволяет это.
  • Вместо этого используйте char Data[1], но обрабатывайте его так, как если бы он был больше, чтобы он перекрывал весь выделенный объект. Это формально неопределенное поведение, но это распространенный метод, поэтому его, вероятно, безопасно использовать с вашим компилятором.
13 голосов
/ 20 июля 2009

Проблема в том, что вы говорите: «Я не могу использовать указатель». Вам придется, и это сделает все намного проще. Эй, realloc даже копирует ваши существующие данные, что вы хотите больше?

Так почему вы думаете, что не можете использовать указатель? Лучше попытаться это исправить.

5 голосов
/ 30 июля 2009

Позвольте мне суммировать два важных момента, которые я вижу в этой теме:

  1. Структура используется для взаимодействия между двумя программами через некоторый механизм IPC
  2. Программа назначения не может быть изменена

Таким образом, вы не можете изменить эту структуру каким-либо образом, потому что целевая программа застряла, пытаясь прочитать ее, как определено в данный момент. Боюсь, вы застряли.

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

Вы можете подумать о написании третьей программы, которая будет служить интерфейсом между ними. Он может принимать «длинные» сообщения, что-то с ними делать и передавать «короткие» сообщения в старую программу. Вы можете легко внедрить это между механизмами IPC.

5 голосов
/ 20 июля 2009

Вы бы перестроили структуру таким образом

typedef struct _MyData
{
   int  Index;
   char Data[256];
} MyData;

И распределять экземпляры с помощью malloc / realloc следующим образом:

my_data = (MyData*) malloc ( sizeof(MyData) + extra_space_needed );

Это уродливый подход, и я бы не рекомендовал его (я бы использовал указатели), но это ответ на ваш вопрос, как это сделать без указателя.

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

2 голосов
/ 30 июля 2009

Проблема в том, как вы задаете вопрос. Не думайте о семантике C: вместо этого думайте как хакер. Объясните точно , как вы в настоящее время вовлекаете свои данные в другой процесс в нужное время, и также , как другая программа знает, где данные начинаются и заканчиваются. Другая программа ожидает строку с нулевым символом в конце? Если вы объявляете свою структуру с символом [300], происходит ли сбой другой программы?

Видите ли, когда вы говорите «передача данных» другой программе, вы можете [a] обманывать другой процесс, копируя то, что вы помещаете перед ним, [b] обманывая другую программу, чтобы позволить вам перезаписать ее обычно «частная» память, или [c] какой-то другой подход. В любом случае, если другая программа может получить ваши большие данные, - это способ получить их.

2 голосов
/ 29 июля 2009

Из того, что вы говорите, похоже, что вы MyData обязательно должны быть статическим блоком данных. В этом случае я думаю, что единственная возможность, которую вы можете открыть, - это каким-то образом (необязательно) связать эти структуры данных вместе, чтобы их можно было повторно собрать в другом процессе.

Вам понадобится и дополнительный член в MyData, например.

typedef struct _MyData
{
   int  Sequence;
   char Data[256];
   int  Index;
} MyData;

Где Sequence обозначает нисходящую последовательность для повторной сборки данных (нулевой порядковый номер будет указывать на конечный буфер данных).

2 голосов
/ 20 июля 2009

Вы можете сделать это следующим образом, не выделяя указатель для массива:

typedef struct _MyData
{
    int Index;
    char Data[1];
} MyData;

Позже вы выделяете так:

int bcount = 256;
MyData *foo;

foo = (MyData *)malloc(sizeof(*foo) + bcount);

перераспределить:

int newbcount = 512;
MyData *resized_foo;

resized_foo = realloc((void *)foo, sizeof(*foo) + newbcount);
0 голосов
/ 30 июля 2009

Как насчет действительно очень простого решения? Не могли бы вы сделать:

typedef struct _MyData
{
   char Data[1024];
   int  Index;
} MyData;

У меня такое чувство, что я знаю, что ваш ответ будет "Нет, потому что другая программа, которую я не контролирую, ожидает 256 байтов" ... И если это действительно ваш ответ на мой ответ, то мой ответ становится: это невозможно.

0 голосов
/ 30 июля 2009

Вы не указываете, для чего используется значение индекса.

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

Данные имеют размер 512 байт, поэтому вы отправляете одну структуру с первыми 256 байтами и индексом = 0, затем другую со следующими 256 байтами в вашем массиве и индексом = 1.

0 голосов
/ 24 июля 2009

Вы не можете повторно реагировать вручную.

Вы можете сделать несколько трюков, с которыми я работал, когда работал над простой системой хранения данных. (очень простая файловая система).

typedef struct
{
    int index ;     
    char x[250];
} data_ztorage_250_char;

typedef struct
{
    int index;      
    char x[1000];
} data_ztorage_1000_char;

int main(void)
{
      char just_raw_data[sizeof(data_ztorage_1000_char)];
      data_ztorage_1000_char* big_struct;
      data_ztorage_250_char* small_struct;
      big_struct = (data_ztorage_1000_char*)big_struct; //now you have bigg struct
      // notice that upper line is same as writing 
      // big_struct = (data_ztorage_1000_char*)(&just_raw_data[0]);

      small_struct = (data_ztorage_250_char*)just_raw_data;//now you have small struct

      //both structs starts at same locations and they share same memory
     //addresing data is 
      small_struct -> index = 250;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...