开发者

Using struct with double-pointer and its memory makeup

开发者 https://www.devze.com 2023-03-23 11:14 出处:网络
I made this little piece of code where I alloc and then free memory for a struct: struct item { int val;

I made this little piece of code where I alloc and then free memory for a struct:

struct item {
    int val;
    int *vectOfInt;
    struct item *next;
};

void relItem(struct item **currItem) {
    struct item *temp;
    int *intTemp;

    temp = *currItem;
    intTemp = (*currItem)->vectOfInt;
    *currItem = (*currItem)->next;
    free(temp);
    free(intTemp);
}

int main() {
    int array[] = {0, 1,开发者_开发技巧 2, 3, 4, 5};
    struct item *list = NULL;

    list = (struct item*) malloc(sizeof(struct item));
    list->val = 0;
    list->vectOfInt = array;
    list->next = NULL;

    relItem(&list);

    return 0;
}

EDIT: code for the comment:

struct item {
    int val;
    struct item *next;
};

void edit(struct item *currItem) {
    currItem->val = 2;
}

int main() {
    struct item *list = NULL;
    list = (struct item*) malloc(sizeof(struct item));
    list->val = 0;
    list->next = NULL;

    edit(list);

    //list-val == 2

    return 0;
}
  • How can I do the same thing without using double-pointer to the struct?

  • Can you explain me why and how this works (both with pointer and double-pointer)?

  • I don't understand how a struct is represented in main memory (for example int a[5]; in memory a is a pointer to the first location of the buffer allocated for the a[5] array)

what is the equal representation for a struct initialized wit ha pointer (struct item *s) ?


-You need to use double pointer since you need to change the pointer to your struct and call by reference is not allowed in C.

-It would not work with a single pointer. Because you want to change the pointer to your object. You do it by the statement *currItem = (*currItem)->next; In order to change it permanently, you need to use a pointer to it. Which makes you use double pointer.

Think of it that way:

you have an integer variable a that you want a function to change its value. You simply call this function with a pointer to the variable a like:

void changeTheValue(int *x)
{
    *x = 7;
}
void main()
{
   int a = 5;
   changeTheValue(&a);
}

and in your case you want to change your pointer's value and you simply pass its pointer to the function.(double pointer) simple as that. If you want to change value of something with a function, then you have to pass its pointer to the function.

-When you make a call to malloc, you want space from it. And you state that you want a space as big as the size of your struct. (Like when you did in here list = (struct item*) malloc(sizeof(struct item));) and malloc allocates a space as big as your struct. If size of your struct is 1 byte then you have a 1 byte space, if it is 4, then you have consecutive 4 bytes. See, this is how your struct is kept in the memory. If you declare a struct variable or an array etc. then your struct is kept in memory like (dunno if it is a good metaphor) an array. The first member comes first, and then the second...

say if you have a struct

struct myStruct
{
    int a;
    float b;
    char c;
};

then the memory looks like


a


b


c

ps: you are making an illegal call to free on the line free(intTemp); you are *free*ing a variable that you didn't *malloc*ed.


How can I do the same thing without using double-pointer to the struct?

You have to use the double pointer.

Can you explain me why and how this works (both with pointer and double-pointer)?

The double-pointer is necessary. Your data structure is a pointer to a structure. You then call a function that needs to modify that pointer. Since parameters are passed by value you have to pass a pointer to the pointer.

I don't understand how a struct is represented in main memory.

Typically structs are laid out sequentially. So the first member will be placed at the beginning of the memory reserved for the struct, the second member will follow it and so on. There are issues of padding and alignment as well, but that's a bit more complex and is something best left to the compiler.


  1. If you want to change the value of list (and you want to) in a different function, you have to give its address, since all parameters in C are passed by value and not by reference.
  2. You give the address to the pointer, because you want to change the pointer.
  3. int a[5] is not a struct, but an array, structs and array are represented in C as a block of memory. When you refer to a member of the struct, you actually refers to an offset from the struct location.

A. You free vertorOfInts when it was not allocated on the heap (with malloc) but on the stack (int array[] = {0, 1, 2, 3, 4, 5}; - local allocation) this is invalid and will make your program (probably to) crash


You can think of it like this: Your data structure is a singly-linked list, where each node is of type T = struct item *. You pass your list around by its head, i.e. its first node. Consumers can take the head and iterate through the entire list by looking at T.next, and a value of NULL means that you're at the end.

The function relItem chops the first node off the list. Since it manipulates the list itself, you have to pass it a pointer to your list head, i.e. T*, which is struct item **. Finally, T = NULL is to be interpreted (and checked for!) as the empty list with no nodes.


This code can work safe and sound without the double pointers:

void relItem(struct item *currItem) { ... }

Call it with relItem(list)

Freeing a pointer does not change it's value. Functions that take double pointers as parameters are usually used when you want to change a pointer (e.g. allocate it or make NULL).

Just be carefull at free(intTemp), it crashes because you're freeing memory from the stack.

0

精彩评论

暂无评论...
验证码 换一张
取 消