0

I am learning pointers these days and while learning generic pointers I came across an issue that if I want to increment the pointer value in a loop for both char and int***, how exactly can I do it. I can increment the pointer easily while dealing with one data type but in the following code, I want to increment the pointer value for both int and char.

while running the code I get the segmentation fault: 11 error message.

#define SIZE 3

enum type_details {is_book, is_article};
typedef struct library
{
    enum type_details type;
    void *item;
}library;

typedef struct item_details
{
    char *title;
    int pages;
}item_details;

int main(void)
{
    item_details details[SIZE];
    library library;

    // input title and pages values for three books
    details[0].title = malloc(SIZE*10);
    details[0].title = "C++";
    details[0].pages = 200;

    // book 2
    details[1].title = malloc(SIZE*10);
    details[1].title = "Java";
    details[1].pages = 300;

    //book 3
    details[2].title = malloc(SIZE*10);
    details[2].title = "Python";
    details[2].pages = 400;

    // displaying values through normal mechanism
    for (int i = 0; i < SIZE; i++)
    {
        printf("item: %i, Book %s with %i pages\n",i , details[i].title, details[i].pages);
    }

    // Displaying values using void pointer
    library.item = details;
    for (int i = 0; i < SIZE; i++)
    {
        printf("item: %i, Book %s with %i pages\n",i ,*(char**)library.item, *(int*)library.item);
         library.item = (int*)library.item + 1;       // error lies here
        library.item = (char**)library.item + 1;      // and here
    }

    free(details[0].title);
    free(details[1].title);
    free(details[2].title);

    return 0;
}


  • Not exactly a duplicate, but this might go a long way towards clarifying things for you: https://stackoverflow.com/questions/58280538/how-to-verify-if-a-void-pointer-void-is-one-of-two-data-types/58281061#58281061 – Yunnosch Jul 06 '20 at 11:25

2 Answers2

1

library.item points to data of type item_details, so you should treat it as such and increment it by sizeof(library.item) because there's no guarantee that sizeof(library.item) == sizeof(int*) + sizeof(char**) as your code assumes. The compiler is free to insert padding bytes into the struct.

So you could do this:

library.item = (char *)library.item + sizeof(item_details)

or:

library.item = (item_details *)library.item + 1
ForceBru
  • 43,482
  • 10
  • 63
  • 98
  • 'library.item = (item_details *)library.item + 1' makes a lot more sense as item_details has a size of int + char. when i ran the program now using it its not showing this output 'item: 0, Book C++ with 200 pages item: 1, Book Java with 300 pages item: 2, Book Python with 400 pages item: 0, Book C++ with -1572852592 pages item: 1, Book Java with -1572852560 pages item: 2, Book Python with -1572852528 pages' – Owais Qayyum Jul 06 '20 at 11:35
  • if you can see the pages has some garbage value – Owais Qayyum Jul 06 '20 at 11:37
1

details[0].title = malloc(SIZE*10); followed by details[0].title = "C++"; is WRONG: You just allocated storage to details[0].title and then you throw that pointer away and replace it with a pointer to the literal string "C++".

free(details[0].title); will next case the seg fault because you want to free something not allocated with malloc.

You must use strcpy: strcpy(details[0].title,"C++");

See also the solution by ForceBru, who also raises a valid point and problem.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
  • Thanks for the suggestion, but without using details[0].title = malloc(SIZE*10); i get segmentation fault. – Owais Qayyum Jul 06 '20 at 11:39
  • @OwaisQayyum okay, it's still wrong, you probably get segmentation fault because of how you're trying to increment the pointer – user253751 Jul 06 '20 at 11:47
  • You must keep the `malloc` call of course (you need the memory) and then copy the string value to the newly allocated memory. – Paul Ogilvie Jul 06 '20 at 15:40