Search code examples
cpointersstructmallocpointer-to-pointer

Compiler error (lvalue required as left operand of assignment) when using malloc


I got 2 structs,a pointer to each struct and a void **stack which points to the pointers of the structs.

my problem is at the line

(*ptr2+*a)=(struct student *)malloc(sizeof(struct student));

*a is a variable that increases by 1 everytime a stud registration happens so i don't allocate memory for the same address over and over again

since i send the address of stud(&stud) at the menu function and then at the input function

*ptr2==stud 

thus

stud[*a]== *(stud+*a)== *(*ptr2+*a)

why is (*ptr2+*a) on the left side of malloc wrong? part of the code

struct student
{
    char flag;
    char surname[256];
    int semester;
};

main()
{
    ...
    struct student *stud;
    menu(stack,stackcopy,reversedstack,&prof,&stud,stacksize,&head);
    ...
}

void menu(void **stack,void **stackcopy,void **reversed,struct professor **ptr1,struct student **ptr2,int size,int *head)
{
    ...
    input(stack,ptr1,ptr2,size,head,&a,&b);
    ...
}


int input(void **stack,struct professor **ptr1,struct student **ptr2,int size,int *head,int *a,int *b)
{
            ...
            done=Push(stack,head,(*(int *)ptr2+*a),size);
            (*ptr2+*a)=(struct student *)malloc(sizeof(struct student));
            stud_input(ptr2,a);
            ...
}

Solution

  • my problem is at the line with

    (*ptr2+*a)=(struct student *)malloc(sizeof(struct student));
    

    Do I cast the result of malloc?

    I have edited this answer because I was completely wrong on the first try. In my head, there was one level of indirection more than you actually have.

    Suppose you want to malloc() a number of entries and assign it to stud, i. e. write it to where stud actually sits.

    If you were up to do it in main(), you'd do

    struct student *stud = malloc(n * sizeof(*stud));
    

    resp.

    struct student *stud;
    stud = malloc(n * sizeof(*stud));
    

    if you want to have space for n entries.

    If you want to do the same in the called function, then you replace stud with *ptr2:

    *ptr2 = malloc(n * sizeof(*stud));
    

    It seems you want to allocate only one entry here. Then you just do

    *ptr2 = malloc(sizeof(*stud));
    

    Be aware that you have only one pointer which you can use to access either one entry (as you seem to want it), or an array of entries allocated appropriately.

    While it is true that

    stud[*a]== *(stud+*a)== *(*ptr2+*a)
    

    you are only allowed to access as many entries as you have allocated. Especially, if you have allocated only as much space as needed one entry, you are only allowed to use

    stud[0] == *stud
    

    both of which is a struct student and cannot be assigned the result of a malloc() call.

    If you do an allocation of, e. g.,

    malloc(10 * sizeof(*stud))
    

    and assign that to stud or to *ptr, you can access more.

    OTOH, (*ptr2+*a) == (stud + *a) == &stud[*a] == &(*ptr2)[*a]. But this is nothing you can assign to, as the compiler tells you, this is not an lvalue. And even if it was not an lvalue, you were not allowed to access it this way: while &stud[0] is exactly stud, &stud[1] points to the element after the one stud points to.

    And as long as you haven't allocated enough for that to exist, this access is invalid for reading, and even so for writing: you cannot change the address of the 2nd element, as it always is the address of the first one plus sizeof(*stud) bytes.

    I am really not completely clear about what you are up to; I suppose you want to allocate an array and to that in the wrong way.