Thread: [C] Pointer to a Pointer to a Structure

  1. #1
    Registered User
    Join Date
    May 2011
    Posts
    6

    Cool [SOLVED] - [C] Pointer to a Pointer to a Structure

    [SOLVED]

    Hi guys, i'm new here.
    I'm not english, so i want to sorry since now, if my english will not be great.
    I write here, cause you're my last chance, i'm not understanding linked list with double pointer.
    Well, i have a structure like this:
    Code:
    struct book{
    int number;
    char *title;
    };
    there is just one user but he/she could have a different number of books
    so i will have something like:
    Code:
    + user
    |-> book1 -> number, title
    |-> book2 -> number, title
    . . .
    |-> bookN -> number, title
    i also know how many books he/she have (i know 'N')

    The problem is that i have to write a function with this prototype:
    Code:
    int book_list(struct book **l, int *num_books);
    this function must to print on stdout the books list of the user, but i don't know how to work with the **l
    I never saw it before, how can i use it?

    Thanks so much .. and sorry again for my english..
    Last edited by LetItB; 05-20-2011 at 01:17 PM. Reason: [SOLVED]

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I'm guessing the user has an array of pointers to books (e.g. struct book *books[N]) which is getting passed to the function. In which case you'd do something like this:
    Code:
    for(i = 0;i < *num_books;++i)
      printf("%d %s\n", l[i]->number, l[i]->title);
    If you understand what you're doing, you're not learning anything.

  3. #3
    Registered User
    Join Date
    May 2011
    Posts
    6
    Thanks, i've done a try with your code and .. it compile, but .. SEGV (segmentation fault)
    this is the code i've tried:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct book{
    int number;
    char *title;
    };
    
    int book_list(struct book **l, int *num_books);
    
    int main(){
    	int *books;
    	int i;	
    	books=(int*)malloc(sizeof(int));
    	*books=3;
    	struct book *list[*books];
    	for(i=0;i<*books; i++){
    		list[i]->number=i;
    		list[i]->title= "ciao";
    	}
    	book_list(list, books);
    		
    	
    
    return EXIT_SUCCESS;	
    }
    
    
    int book_list(struct book **l, int *num_books){
    int i;	
    	for(i = 0;i < *num_books;++i)
      printf("number: %d title: %s\n", l[i]->number, l[i]->title);
      return EXIT_SUCCESS;
      }
    i think the problem is in 'list' initialization.
    I have initialized 'list' as you said .. i have no idea how to do with a malloc..
    What do you think about?
    Thanks so much!

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Code:
    struct book *list[*books];
    You're declaring an array of pointers to book structs. There's no actual place to store book info. You have two options:
    1. Allocate space before setting the book number or title: list[i] = malloc(sizeof(*list[i]))
    2. Create at array of plain old structs, instead of pointers to struct, and access members using the . operator
    Code:
        struct book list[*books];  // notice I dropped the *
    
        for (i = 0; i < *books; i++) {
            list[i].number = i;  // . operator instead of ->
            list[i].title = "ciao";
        }
        book_list(&list, books);
    I prefer method 2 since you don't seem to show need for dynamically allocating each element of the array.

  5. #5
    Registered User
    Join Date
    May 2011
    Posts
    6
    I've compiled the code as you suggested me:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct book{
    int number;
    char *title;
    };
    
    int book_list(struct book **l, int *num_books);
    
    int main(){
    	int *books;
    	int i;	
    	books=(int*)malloc(sizeof(int));
    	*books=3;
        struct book list[*books];  // notice I dropped the *
    
        for (i = 0; i < *books; i++) {
            list[i].number = i;  // . operator instead of ->
            list[i].title = "ciao";
        }
        book_list(&list, books);	
    	
    
    return EXIT_SUCCESS;	
    }
    
    
    int book_list(struct book **l, int *num_books){
    int i;	
    	for(i = 0;i < *num_books;++i)
      printf("number: %d title: %s\n", l[i]->number, l[i]->title);
      return EXIT_SUCCESS;
      }
    But the compiler say:
    Code:
    gcc dplist.c -o dplist
    dplist.c: In function ‘main’:
    dplist.c:22:5: warning: passing argument 1 of ‘book_list’ from incompatible pointer type
    dplist.c:9:5: note: expected ‘struct book **’ but argument is of type ‘struct book (*)[(unsigned int)(*books)]’
    i've tried to call book_list in other two ways (all wrong):
    book_list(list, books);
    and
    book_list(*list,books);


    Any idea?

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The way I see it, you are not using dynamic memory allocation properly. You don't actually need to dynamically allocate the number of books, but it may make sense to dynamically allocate the list of books, but you ended up using a variable length array for that. I would expect something like this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct book {
        int number;
        char *title;
    };
    
    int book_list(struct book **l, int *num_books);
    
    int main() {
        int num_books = 3;
        struct book *list = malloc(sizeof(*list) * num_books);
        
        /* ... */
    
        book_list(&list, &num_books);
    
        free(list);
        return EXIT_SUCCESS;
    }
    
    int book_list(struct book **l, int *num_books) {
        int i;
        for (i = 0; i < *num_books; ++i)
            printf("number: %d title: %s\n", l[i]->number, l[i]->title);
        return EXIT_SUCCESS;
    }
    Observe that my indentation (and formatting) is more consistent than yours.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Yeah, I didn't think my response through too carefully -- it would require changing the declaration of book_list, which you can't do. Use laserlight's method.

  8. #8
    Registered User
    Join Date
    May 2011
    Posts
    6
    I've rewrited the code with a better indentation, also using your method, but it still SEGV

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct book {
        int number;
        char *title;
    };
    
    int book_list(struct book **l, int *num_books);
    
    int main() {
        int num_books = 3;
        int i;
        struct book *list = malloc(sizeof(*list) * num_books);
        for (i = 0; i < num_books; i++) {
            list[i].number = i;
            list[i].title = "ciao";
            printf("[MAIN] number: %d title: %s\n", list[i].number, list[i].title); 
        }
    
        book_list(&list, &num_books);
        free(list);
        return EXIT_SUCCESS;
    }
    
    int book_list(struct book **l, int *num_books) {
        int i;
        for (i = 0; i < *num_books; ++i)
            printf("[BOOK_LIST] number: %d title: %s\n", l[i]->number, l[i]->title);
        return EXIT_SUCCESS;
    }
    Could you explain me, why it SEGV?
    I mean, i've allocated 3 structures, i can write into these structures (the printf into the main function help me to check if it can write into the structures), but i cannot print them in stout .. i'm asking why..
    Do you know the answer? Please, i know i'm boring, but i need to understand..

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    l[i] doesn't exist except for i = 0. (*l)[i], on the other hand, exists for i=0, 1, and 2.

    (EDIT: Even though you got it to work, I realize this is pretty brief. l[i] would work if you had an array of struct* things; but that's not really what we have, we have a pointer to an array of structs, so we follow the pointer to get to the array, then use the brackets to select one element in that array. By analogy, you can look at the thread "2D-array pointer" that's also toward the top of the page about int *p[2] versus int (*p)[2].)
    Last edited by tabstop; 05-20-2011 at 01:04 PM.

  10. #10
    Registered User
    Join Date
    May 2011
    Posts
    6
    Great!
    I really, really thanks you!
    This is the right way:
    Code:
    int book_list(struct book **l, int *num_books) {
        int i;
        for (i = 0; i < *num_books; ++i)
            printf("[BOOK_LIST] number: %d title: %s\n", (*l)[i].number, (*l)[i].title);
        return EXIT_SUCCESS;
    }
    I should modify the title with "[SOLVED]"?

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Oh yeah. But hold on: you should simplify:
    Code:
    int book_list(struct book *list, int num_books) {
        int i;
        for (i = 0; i < num_books; ++i)
            printf("[BOOK_LIST] number: %d title: %s\n", list[i].number, list[i].title);
        return EXIT_SUCCESS;
    }
    There is no point adding another level of indirection when you don't need it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    So you passed in &list, which is the address of a pointer to a book struct, i.e. a pointer to a pointer to a book struct. Inside book_list, it doesn't know whether you passed it the address of what is effectively an array, or the address of a pointer to a single element. You did the former, but treat it like the latter. You need to dereference l before indexing the array. You need
    Code:
    (*l)[i].number
    *l gives you the address of the memory you allocated in main, the start of the array
    (*l)[i] gives you the i'th element of that array. You need the parens because [] is higher precedence than * (dereference)
    (*l)[i] is a book struct (not a pointer to a book struct), hence use of the . operator

    EDIT: wow, way too slow. Beaten twice! @ laserlight: his OP said he must use that declaration of book_list, with the **.

  13. #13
    Registered User
    Join Date
    May 2011
    Posts
    6
    @tabstop: Thanks for the edit!
    @anduril462: exactly what i was looking for! Thanks so much for the explaination!
    @laserlight: i must use it, cause my teacher wants..
    Anyway, thanks to all of you.

    That's a present for you:
    http://1.bp.blogspot.com/-gUDVGJSZc3...ni-ricette.jpg
    Try to guess where i'm writing from..

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Referencing pointer inside a structure pointer
    By SasDutta in forum C Programming
    Replies: 2
    Last Post: 11-11-2010, 11:33 AM
  2. pointer of pointer to structure
    By aayu09 in forum C Programming
    Replies: 3
    Last Post: 04-08-2010, 09:04 PM
  3. Replies: 3
    Last Post: 10-30-2009, 04:41 PM
  4. Replies: 9
    Last Post: 06-13-2009, 02:31 AM
  5. Replies: 4
    Last Post: 08-27-2007, 11:51 PM

Tags for this Thread