Назначение указателя на строку внутри структуры и доступ к нему

#c #pointers #c99 #struct #memcpy

#c #указатели #c99 #структура #memcpy

Вопрос:

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

 typedef struct {
    void **storage;
    int numStorage;
} Box;
  

Поле инициализируется как таковое:

     b->numStorage = 1000000; // Or set more intelligently
    Box *b = malloc(sizeof(Box));
    // Create an array of pointers
    b->storage = calloc(b->numStorage,sizeof(void *));
  

Для того, чтобы задать строку, я использую эту функцию:

 void SetString(Box *b, int offset, const char * key)
{
    // This may seem redundant but is necessary
    // I know I could do strcpy, but made the following alternate
    // this isn't the issue
    char * keyValue = malloc(strlen(key)   1);
    memcpy(keyValue, key, strlen(key)   1);

    // Assign keyValue to the offset pointer
    b->storage[offset*sizeof(void *)] = amp;keyValue;

    // Check if it works
    char ** ptr = b->storage[offset*sizeof(void *)];

    // It does
    printf("Hashcode %d, data contained %sn", offset, *ptr);

}
  

Проблема заключается в том, что когда я пытаюсь извлечь его снова, с точно таким же смещением:

 // Return pointer to string
void *GetString(const Box *b, int offset, const char *key)

    char ** ptr = b->storage[offset*sizeof(void *)];
    if (ptr != NULL) {
        printf("Data should be %sn", *ptr);
        return *ptr;
    } else {
     return NULL;
    }
  

Возвращаемый указатель является тарабарщиной. Что может быть не так?

Ответ №1:

Вам не нужно указывать фактическое смещение памяти при доступе к массивам. Просто укажите ему индекс, и вы получите правильный элемент.

Итак, в вашем третьем блоке кода:

 b->storage[offset] = keyValue;
  

И в вашем четвертом:

 char *ptr = b->storage[offset];
if (ptr != NULL) {
    printf("Data should be %sn", ptr);
    return ptr;
} else {
 return NULL;
}
  

Также, во втором блоке кода, b->numStorage уже было установлено?

Ответ №2:

 b->storage[offset*sizeof(void *)] = amp;keyValue;
  

Это сохраняет адрес локальной переменной keyValue в массиве. Как только функция завершается, этот адрес становится недействительным. Я думаю, вы хотите:

 b->storage[offset*sizeof(void *)] = keyValue;
  

а затем внесите соответствующее изменение при извлечении.

Ответ №3:

Не так ли:

 b->storage[offset*sizeof(void *)] = amp;keyValue
  

установить хранилище[offset*sizeof(void*)] таким образом, чтобы оно указывало на адрес локальной переменной KeyValue? т.е. больше не действует после возврата функции