проблема структуры и массива в C - PullRequest
0 голосов
/ 24 марта 2011

Вот проблема:
У меня есть такая структура:

struct{
    Variable a;
    Variable 2;
    char ch[1];
}

Мне нужно указать ch на другой struct, содержащий несколько char массивов. Нет, я не могу изменить первое определение структуры вообще. Мне просто нужно, как поместить первый байт моего второго struct в ch[1], и я просто не знаю, как это сделать. Пожалуйста, помогите мне. Благодаря.

Ответы [ 6 ]

5 голосов
/ 24 марта 2011

Вы не можете "указать" массив на что-то другое, потому что массив не является указателем.Массив из одного char - это просто массив, в котором вы можете хранить одно значение char.

Если вы не можете изменить определение с массива на указатель, то вы не можете сделать это«точка».Боюсь, это так просто.

2 голосов
/ 24 марта 2011

Это очень распространенная парадигма в C. Последний символ - просто заполнитель для переменных данных, и в действительности вы будете выделять больший буфер и переполнять 1 символ.Это совершенно законно.

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

То, что вам нужно вместо char[1], этоуказатель (на другую структуру).

Давайте дадим вашей структуре имя:

typedef struct{
    Variable a;
    Variable 2;
    char ch[1];
} Element;

в вашем коде:

Element * elt = malloc( sizeof( Element ) + sizeof( CharArrayStruct* ) - 1);
 /* fill your struct */
*(CharArrayStruct **)elt.ch = &myCharArrayStruct;
/* later on reading it back */
CharArrayStruct * pcas = *(CharArrayStruct **)elt.ch;

Примечание elt.ch - этоадрес начала массива, а не символ.Обратите внимание, что его содержимое - OtherStruct*, поэтому оно должно быть приведено к CharArrayStruct**

1 голос
/ 24 марта 2011

Вы можете придумать третий struct:

struct c {
    struct a *a;
    struct b *b;
    struct c *next;
}

Добавляйте новый элемент в заголовок каждый раз, когда вы хотите сохранить ассоциацию от вашего struct a до вашего struct b - когда вам нужно найти один из них, просмотрите связанный список, выполнив сравнение указателей .a, пока не найдете подходящий и не вернете .b.

Не забудьте удалить эти записи из связанного списка, когда вы free() struct a объекты, и не забудьте NULL .b членов, когда вы free() struct b объектов.

0 голосов
/ 24 марта 2011

Во-первых, не ясно, что вы хотите сделать.Невозможно "указать" на другую структуру, используя однобайтовое значение.Во-вторых, не имеет смысла помещать первый байт второй структуры в ch [0], не делая ничего другого.

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

Выделив несколько дополнительных байтов, вы получите следующий макет в памяти:

+----
| Variable a
| Variable 2 (sic)
| ch[0]
+------ Extra memory below:
| ch[1]
| ...
| ch[N]
+------

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

p = malloc(sizeof(Element) + N);

Вы можете получить доступ к элементу, например p->ch[4], и получить доступ к ch в виде строки, используя p->ch.

Теперь этодо вас, чтобы заполнить массив ch строкой (или чем угодно), которую вы хотите.

0 голосов
/ 24 марта 2011

Если вы имеете в виду то, что вы буквально говорите в фактическом теле вопроса («Мне просто нужно кое-что, как поместить первый байт моей второй структуры в ch[1], и я просто не знаю, как это сделать».),и я игнорирую первое предложение, которое говорит о «наведении», вы можете сделать это так:

struct{
    Variable a;
    Variable 2;
    char ch[1];
} my_struct_that_cant_be_changed;

struct my_other_struct x;

my_struct_that_cant_be_changed.ch[0] = *(char *) &x;

Это просто читает первое char из другой структуры (в переменной x) иприсваивает это значение в массиве из 1 символа первой структуры.

Обратите внимание, что это кажется мне совершенно бессмысленным, но оно делает (вроде) то, что вы хотите.

0 голосов
/ 24 марта 2011

Я не думаю, что это можно сделать безопасным способом, по крайней мере, если только вы не находитесь в среде с небольшим объемом памяти. Один символ (который является вашим полем ch) состоит только из 1 байта; это просто недостаточно битов, чтобы указать на любую область памяти в вашей виртуальной памяти. Даже если вы преобразуете это char в (void *), вы не сможете с ним обращаться к подавляющему большинству своей памяти.

Возможно, вам следует отступить назад и сказать нам, что вы на самом деле пытаетесь достичь, а не то, что, по вашему мнению, вам нужно сделать, чтобы выполнить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...