简体   繁体   中英

Pointer arithmetic not working in a linked list pointer?

I have a linked list, and I want to do decrement the pointer to the linked list pointer, but there are some issues.

For below C program:

#include<stdio.h>
#include<stdlib.h>

struct node
{
    int data;
    struct node *next;
};

int main()
{
    /*Create an empty list*/
    struct node *head = NULL;

    /*Set the first node of list*/
    head = malloc(sizeof(struct node));
    head->data = 1;
    head->next = NULL;

    struct node *head1 = head;

    /*Set the second node of list*/
    head1->next = malloc(sizeof(struct node));
    head1 = head1->next;
    head1->data = 2;
    head1->next = NULL;

    /*Print 1st and 2nd node data*/
    printf("%d ",head->data);
    head = head->next;
    printf("%d ",head->data);

    /*Decrement head. As head was pointing to 2nd node, after head-- it should point to first node ??*/
    head--;
    printf("%d \n",head->data);

    return 0;
}

I am expecting below output:

1 2 1 

However I am getting below output:

User $ ./a.out
1 2 0 
User $

So it looks like the head-- I did at the end did not really decrement head by 1 (if it did head would be pointing to the first node before executing last printf).

So cant do increment or decrement a linked-list pointer ? Like we do for normal pointer ? For ex: For a[] we do a++ or a-- to make a point to next or precious index.

NOTE: I JUST REALIZED THAT LINKED LIST NODES ARE NOT IN CONTIGUOUS MEMORY LOCATION, SO DOING A HEAD-- TO POINT TO PREVIOUS NODE DOES NOT MAKE SENSE.

Thank you all who answered or commented.

When you use malloc() , you allocate new memory location from RAM (cash, or register), which located in a random area. So, when you write head--; , you move to completely different area, that you want. Try use doubly linked list.

Simple pointer arithmetic only works for contiguous data structures. A linked list is non-contiguous.

When you allocate a new object, it is given a new memory location that is not contextually bound by the memory location of the previous item in the list.

When you increment or decrement a pointer the value of the pointer is changed by the size of the type of the pointer. This is more than likely going to point outside the linked list.

What you are trying to do works with arrays since array items are allocated in contiguous memory.

You need a doubly linked list with both next and previous pointers. So you can get back to an element's predecessor.

Your pointer head points to the memory you allocated for the node it points to - nothing else. You have no information as to what's in the vicinity of that pointer and can't assume anything about where memory from malloc() is located outside of it being 'suitably aligned for any purpose', if I remember the standard correctly.

The answer is NO , you can only use the pointer arithmetic to move the pointer a number of units of the pointer type, like this

char array[2] = {'a', 'b'};

print("%c\n", *(array + 0));
/*             ~~~~~~~~~~~                         */
/*                  ^ points to the address of 'a' */
print("%c\n", *(array + 1));
/*             ~~~~~~~~~~~                                                */
/*                  ^ points to 'b', i.e. 1 byte after the address of 'a' */

will output

a
b

but the linked list, is linked to the next element by a pointer which is a member of the list structure, so incrementing it doesn't make sense, list++ is actually equivalent to

list = ((char *)list) + sizeof(*list)

so when you increment the pointer like this, it's not pointing to the next node it's pointing sizeof(struct node) bytes after the location it was pointing to prior to the incrementation.

To make the pointer, point to the next node you need

list = list->next;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM