Как я могу сохранить указатель на смещенное место в области памяти Malloced в C? - PullRequest
0 голосов
/ 22 ноября 2011

Я пытаюсь сделать очень простой Hashtable с библиотеками, которые я получил.Строка, которую я пытаюсь сделать, содержит либо C-строку, либо int в качестве ключа.Значение может быть 4 разных типов.Если это структура, я пытаюсь сохранить указатель в области памяти с ошибками.Однако в моем мире это не следует той же логике, что и поля без указателей, и я получаю:

error C2106: '=' : left operand must be l-value when I try to store pointer as value:

Вот код

static void MakeRow(UtiHashtable_t *Hashtable, void *Key, void *Value, void *Row)
{
    int     KeySize, ValueSize;

    KeySize = sizeof(char) * Hashtable->KeyStringLength;
    ValueSize = GetValueSize(Hashtable);
    Row = malloc(KeySize + ValueSize);

    if (Hashtable->KeyType ==  MY_HASHTABLE_TYPE_STRING)  
        MyStrcpy((char *)Row, (char *)Key, Hashtable->KeyStringLength); 
    else if (Hashtable->KeyType ==  MY_HASHTABLE_TYPE_INT)
        ((int *)Row)[0] =  *(int *)Key;
    else
        MyAssert(0);

    switch (Hashtable->ValueType)
    {
    case MY_HASHTABLE_TYPE_STRING:
        MyStrcpy((char *)Row + KeySize, (char *)Value, Hashtable->ValueStringLength); 
        break;
    case MY_HASHTABLE_TYPE_INT: 
        *(int *)((char *)Row + KeySize) =  *(int *)Value;
        break;
    case MY_HASHTABLE_TYPE_DOUBLE: 
        *(double *)((char *)Row + KeySize) =  *(double *)Value;
        break;
    case MY_HASHTABLE_TYPE_STRUCT: 
        (int *)((char *)Row + KeySize) = (int *)Value;
        break;
    default:
        MyAssert(0);
    }
}

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

Компилятор позволяет:

(int *)Value = (int *)Key;

, так почему бы и нет:

(int *)((char *)Row + KeySize) = (int *)Value;

Спасибо & BR -Matti

Ответы [ 2 ]

1 голос
/ 22 ноября 2011

Использование приведений к lvalue не рекомендуется.

Кроме того, некоторые системы не позволяют размещать int s или указатели в произвольных местах памяти из-за проблем с выравниванием.

Что вам нужно сделать, это memcpy указать значение указателя туда, куда вы хотите. И когда вы хотите использовать указатель, вам нужно memcpy вернуть его к переменной указателя.

0 голосов
/ 22 ноября 2011

Вы остановили разыменование * на левой стороне, поэтому назначение больше не имеет никакого смысла.

...