Thread: return an array of structs

  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    return an array of structs

    So I have been obsessing over creating a merge sort for linked lists. I can do a merge sort with an int array fine, but there seems to be much less flexability dealing with an array of structs which is giving me a lot of problems. How do you return an array of structs? (After trying it and googling I am not sure if it is possible, strangely). Trying to pass such a list as an argument seems even less possible.

    Ideally, I would to do this with just an array of struct pointers, or an array of any kind of pointers but my compiler will not let me cast them into struct pointers in a useful way.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You can not return an array from a function, no matter what.

    You can pass in an array and fill it in, or you can return a pointer, or pass in a pointer to pointer and allocate space (and either pass in a pointer to an itneger that gives you the number of items, or return the number of items if you pass a pointer to pointer).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by matsp View Post
    You can not return an array from a function, no matter what.

    You can pass in an array and fill it in, or you can return a pointer, or pass in a pointer to pointer and allocate space (and either pass in a pointer to an itneger that gives you the number of items, or return the number of items if you pass a pointer to pointer).

    --
    Mats
    If I pass in an array, I have to declare it's length?
    Code:
    void testfunc (struct *ray[10]) {
    If I return a pointer (eg, struct *ptr (struct *ray) {) should I allocate for the array it points to inside the function, or before I call it?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Here's an example of the wierdness I'm talking about:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct Test {
    	char *name;
    	int age;
    } ;  
    
    void testfunc (struct Test *examp) {
    	if ((examp=realloc(examp,3*sizeof(*examp)))==NULL) puts ("malloc fail");
    	puts("HERE");
    	fflush(stdout);
    	examp[0].name=malloc(5);
    	strcpy(examp[0].name,"five");
    	examp[0].age=5;
    	examp[1].name=malloc(5);
    	strcpy(examp[1].name,"four");
    	examp[1].age=4;
    	examp[2].name=malloc(5);
    	strcpy(examp[2].name,"nine");
    	examp[2].age=9;
    }
    
    int main () {
    	int i=0;
    	struct Test *examp=malloc(sizeof(*examp)); 	 
    	
    	testfunc (examp);
    	printf("sizeof *examp:%d sizeof examp:%d\n",sizeof(*examp),sizeof(examp));
    	printf("%s is %d\n", examp[0].name,examp[0].age);
    	for (i=0;i<3;i++) {puts("X");printf("%s is %d\n", examp[i].name,examp[i].age);}
    	
    }
    Everything is fine. I am surprised that *examp is 8 bytes while examp is 4 bytes, but whatever (???). However, I am a little worried the realloc doesn't really realloc inside the function, because this causes a segfault:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct Test {
    	char *name;
    	int age;
    } ;  
    
    void testfunc (struct Test *examp) {
    	if ((examp=malloc(3*sizeof(*examp)))==NULL) puts ("malloc fail");
    	puts("HERE");
    	fflush(stdout);
    	examp[0].name=malloc(5);
    	strcpy(examp[0].name,"five");
    	examp[0].age=5;
    	examp[1].name=malloc(5);
    	strcpy(examp[1].name,"four");
    	examp[1].age=4;
    	examp[2].name=malloc(5);
    	strcpy(examp[2].name,"nine");
    	examp[2].age=9;
    }
    
    int main () {
    	int i=0;
    	struct Test *examp; 	 
    	
    	testfunc (examp);
    	printf("sizeof *examp:%d sizeof examp:%d\n",sizeof(*examp),sizeof(examp));
    	printf("%s is %d\n", examp[0].name,examp[0].age);
    	for (i=0;i<3;i++) {puts("X");printf("%s is %d\n", examp[i].name,examp[i].age);}
    	
    }
    Why can't I malloc the struct array inside another function and return it?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    May 2008
    Posts
    53
    Quote Originally Posted by MK27 View Post
    Everything is fine. I am surprised that *examp is 8 bytes while examp is 4 bytes, but whatever (???).
    examp is a pointer, which (on a 32-bit system) is 4 bytes in size. *examp is what its points to, which in this case is the size of your structure.

    Quote Originally Posted by MK27 View Post
    Why can't I malloc the struct array inside another function and return it?
    You can. The drawback to this technique is that the callers of your function will have to remember to free() the array.

    --
    Computer Programming: An Introduction for the Scientifically Inclined

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    However, if you want to pass in a pointer, to be filled in inside the function, you should pass a pointer to a pointer - just like if you want to change an integer inside a function, you need to pass a pointer to an integer.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User slingerland3g's Avatar
    Join Date
    Jan 2008
    Location
    Seattle
    Posts
    603
    What you need or have is a 2d array and you need to properly set aside memory for that as well.

    Code:
    int **createMyExamp(int r, int c)
    {
       int i;
       int **examp = malloc(r * sizeof(int *));
       for (i = 0 ; i < r; i++)
          examp[i] = malloc (c * sizeof(int));
      return examp;
    }

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    int (*p)[dimension2] = malloc(dimension1 * sizeof(type) + dimension2);
    That you need a p2p to create a 2D array is a myth. All you need is the correct type.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Mar 2009
    Posts
    30
    Changed the function to return the structure and this works

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Test {
            char *name;
            int age;
    } ARF ;
    
    int main () {
            int i;
            ARF *examp;
    
            ARF *testfunc() ;
    
            examp = testfunc();
    
            printf("sizeof *examp:%d sizeof examp:%d\n",sizeof(*examp),sizeof(examp));
            printf("%s is %d \n", examp[0].name, examp[0].age );
    
             for (i=0;i<3;i++) printf("%s is %d\n", examp[i].name,examp[i].age);
    
            return 0 ;
    
    }
    
    ARF *testfunc()
    {
            ARF *bexamp ;
            if (  ( bexamp =  (struct Test *) malloc( 3 * sizeof(ARF) ) ) == NULL)   puts ("malloc fail");
    
            puts("HERE");
            fflush(stdout);
    
            bexamp[0].name=(char *) malloc ( (strlen("five")+1) * sizeof(char ) );
            strcpy(bexamp[0].name,"five");
            bexamp[0].age=5;
    
            bexamp[1].name=(char * ) malloc(5 * sizeof(char ) );
            strcpy(bexamp[1].name,"four");
            bexamp[1].age=4;
    
            bexamp[2].name=(char * ) malloc(5 * sizeof(char ) );
            strcpy(bexamp[2].name,"nine");
            bexamp[2].age=9;
    
            return bexamp ;
    }

  10. #10
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    you should not use null-pointer (after failed malloc)
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  11. #11
    Registered User
    Join Date
    Oct 2009
    Posts
    46
    Quote Originally Posted by Elysia View Post
    Code:
    int (*p)[dimension2] = malloc(dimension1 * sizeof(type) + dimension2);
    That you need a p2p to create a 2D array is a myth. All you need is the correct type.
    Sorry to dig this up, but I've been looking into this thread and got some nice info. I have a few doubts regarding the quoted statement, can someone elaborate on it? What is p2p? (In this context, I think its not peer to peer)


    I believe this is an answer to , if yes how does it apply?

    Code:
    int **createMyExamp(int r, int c)
    {
       int i;
       int **examp = malloc(r * sizeof(int *));
       for (i = 0 ; i < r; i++)
          examp[i] = malloc (c * sizeof(int));
      return examp;
    }
    Thanks!

  12. #12
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by sugarfree View Post
    What is p2p?
    A "pointer to a pointer", eg:
    Code:
      int **examp = malloc(r * sizeof(int *));
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #13
    Registered User
    Join Date
    Oct 2009
    Posts
    46
    haha, silly me. That was easy.

  14. #14
    Registered User
    Join Date
    Oct 2009
    Posts
    46
    Another question, what is the point of having examp[i] = malloc (c * sizeof(int)); in slingerland3g post? Is this examp[r][c]?

  15. #15
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by sugarfree View Post
    Is this examp[r][c]?
    Yes.

    example[r] is a pointer and needs c*sizeof(int) bytes allocated to it to store an array (row) of ints.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. New string functions
    By Elysia in forum C Programming
    Replies: 11
    Last Post: 03-28-2009, 05:03 AM
  2. need help program crashing
    By tunerfreak in forum C++ Programming
    Replies: 14
    Last Post: 05-22-2006, 11:29 AM
  3. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  4. Inserting new member into array of structs
    By cathym in forum C Programming
    Replies: 6
    Last Post: 04-17-2005, 07:10 AM
  5. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM