Question

I have a little issue - For some reason when I try to reallocate memory to a pointer to pointer of a struct to increase the amount of memory blocks by one for an extra struct in a function, Intellisense tells me that the "expression must be a modifiable lvalue". Thing is, if I try to allocate to the input itself, all is fine - the problem is when I try to reallocate to input + 1.

The structs in use:

struct Entry_t
{
    char *word;
    Year **years;
    char **syn;
    Meaning **mean;
    Entry *next;
};

struct Mean_t
{
    char *word;
    Entry **enword;
    Meaning *next;
};

The functions:

/*
| Function: IsInMean
| Action: Checks whether the meaning already exists
| Input: Master meaning struct, the string
| Returns: The address of the necessary place if yes, NULL otherwise
*/
Meaning *IsInMean(Meaning *MEANS, char *str)
{
    if(MEANS)
    {
        if(strcmp(MEANS->word,str) == 0)
            return MEANS;
        else
            return IsInMean(MEANS + 1,str);
    }
    else
        return MEANS;
}

/*
| Function: FindMeanPlace
| Action: Checks where to wedge the meaning.
| Input: The master Meanings dictionary, the string
| Returns: The address of the place where to wedge, NULL if all are bigger.
*/
Meaning *FindMeanPlace(Meaning *MEANS, char *str)
{
    int cmp;
    if((cmp = strcmp(MEANS->word,str)) > 0)
        return NULL;
    else if(cmp < 0 && strcmp(MEANS->next->word,str) > 0)
        return MEANS;
    else
        return FindMeanPlace(MEANS + 1,str);
}

/*
| Function: NewMean
| Action: Creates and initializes a new meaning struct
| and places in it a new entry
| Input: Standard input, new entry, string with the meaning
| Returns: The address of the new meaning struct
*/
Meaning *NewMean(STANDARD_INPUT,Entry *new_e, char *str)
{
    Meaning *temp = (Meaning*)malloc(sizeof(Meaning));
    InitMean(temp);
    temp->word = (char*)calloc(strlen(str) + 1,sizeof(char));
    strcpy(temp->word,str);
    *(temp->enword) = new_e;
    return temp;
}

/*
| Function: SetMean
| Action: Sets the meanings field of an entry
| Input: Standard input, address of the new entry and
| the appropriate sub-string
| Returns: nada
*/
void SetMean(STANDARD_INPUT, Entry *new_e, char *str)
{
    char *cutout, delim[] = ",_";
    char **temp = NULL;
    int len = 0, cmp, index;
    Entry **entemp, *etemp;
    Meaning *input, *mtemp;
    cutout = strtok(str,delim);
    while(cutout)
    {
        temp = (char**)realloc(temp,(len + 1)*sizeof(char*));
        if(!temp)
            Pexit(STANDARD_C);
        *temp = (char*)calloc(strlen(cutout) + 1,sizeof(char));
        if(!(*temp))
            Pexit(STANDARD_C);
        strcpy(*temp,cutout);
        temp++;
        len++;
        cutout = strtok(NULL,delim);
    }
    QsortCust(STANDARD_C,temp,len + 1);
    while(temp)
    {
        index = 0;
        if(input = IsInMean(MEANS,*temp))
        {
            entemp = input->enword;
            if(strcmp(entemp[0]->word,new_e->word) > 0)
                //entemp + 1 = (Entry**)realloc(entemp,sizeof(entemp) + sizeof(Entry*));  "expression must be modifiable lvalue"
            while(entemp + index)
            {
                if((cmp = strcmp((entemp[index])->word,new_e->word)) < 0 && strcmp((entemp[index + 1])->word,new_e->word) > 0)
                {
                    //(entemp + index + 1) = (Entry**)realloc(entemp + index,sizeof(entemp + index) + sizeof(Entry*));  "expression must be modifiable lvalue"
                    //if(!(entemp + index + 1))
                    //  Pexit(STANDARD_C);
                }
                else if(cmp <0)
                {
                    index++;
                }
            }
        }
        else
        {
            input = FindMeanPlace(MEANS,*temp);
            mtemp  = input->next;
            input->next = NewMean(STANDARD_C,new_e,*temp);
        }
    }
}

STANDARD_INPUT is defined as the master dictionary (the first Entry*), the yearly dictionary (first Year*) and the meanings dictionary (first Meaning*). STANDARD_C is defined as the names of the variables from the standard input.

Was it helpful?

Solution

If what you want to do (per comments) is enlarge the dope vector entemp itself, but add the new space to the beginning instead of the end, you cannot do that with a single operation. realloc must always be passed an un-offset pointer received from malloc (or calloc or a previous call to realloc), and it always adds the space at the end. You have to slide everything down yourself, using memmove. For instance:

nelements += 1;
entemp = realloc(entemp, nelements * sizeof(Entry *));
assert(entemp);
memmove(entemp, entemp+1, (nelements - 1) * sizeof(Entry *));

Also, as I just noticed this: sizeof(entemp) does not return the allocation size of the memory block pointed to by entemp. It returns the size of the pointer itself. There is no way to retrieve the allocation size of blocks on the C heap; you have to track them yourself. This is what my nelements variable is doing, above.

Closely related obligatory tangential comment: don't cast the return value of realloc, just like you don't cast the return value of malloc or calloc. This is not just a style thing: casting when you don't need to can hide bugs!

Less closely related but still obligatory style nitpick: NAMES_IN_ALL_CAPS are, by longstanding convention, reserved for constants. Do not use them for variable names. And your magic macros that expand to entire variable / argument declarations are Right Out.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top