CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Oct 2005
    Posts
    6

    Passing array of struct as reference

    Hi there,
    I'm trying to pass a pointer to struct to a function , the function has to process and store data in the array. This is the code, when running the program it crushes. I don't want to return the pointer (like: return MyArrayPtr), I need to point the passed pointer to the new memory address.
    Thanks, Eli

    #include <stdio.h>
    #include <malloc.h>

    typedef struct
    {
    char name[80];
    int id;
    }MyStruct;

    int MyFunc(MyStruct *MyPtr);

    void main()
    {
    int i;
    MyStruct *MyPtr = NULL;

    MyFunc(MyPtr);

    for(i=0;i<100;i++)
    {
    printf("Name: %s, id: %d\n",MyPtr[i].name, MyPtr[i].id );
    }
    }

    int MyFunc(MyStruct *MyPtr)
    {
    int i;

    MyStruct *MyArrayPtr = (MyStruct*)malloc(sizeof(MyStruct)*100);

    for(i=0;i<100;i++)
    {
    MyPtr[i].id = i;
    sprintf(MyPtr[i].name, "Eli-%d", i);
    }
    MyPtr = MyArrayPtr;
    return 0;
    }

  2. #2
    Join Date
    Oct 2002
    Location
    Germany
    Posts
    6,205

    Re: Passing array of struct as reference

    [ redirected ]

    Regards,
    Siddhartha

  3. #3
    Join Date
    Feb 2002
    Posts
    4,640

    Re: Passing array of struct as reference

    The problem is in your function declaration. You need to pass the pointer by reference, so that you can return the proper value to the caller:
    Code:
    int MyFunc(MyStruct* &MyPtr)
    This way, the calling function will get the proper pointer back. Also, don't forget a call to 'free' after the for loop in your main program, to release the memory you allocated.

    Viggy

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Passing array of struct as reference

    Quote Originally Posted by elireu
    Hi there,
    I'm trying to pass a pointer to struct to a function , the function has to process and store data in the array. This is the code, when running the program it crushes.
    You are changing the value of the pointer within the function. The pointer is local to the function, therefore you don't see the new value on return. It's as if you did this:
    Code:
    void foo(int i)
    {
       i = 10;
    }
    
    int main()
    {
        j = 6;
        foo( j );
    }
    Is the value of j on return 10? Or is it still 6? Of course it's still 6. The same rule applies to pointers:
    Code:
    void foo(int *pLocal)
    {
       pLocal = new int [10];
    }
    
    int main()
    {
        int *p=NULL;
        foo( p );
    }
    Is the value of p what was assigned in foo(), or is it still NULL? It is still NULL.

    In general to change 'x' in a function and have the changes remain when you return, you pass a pointer or reference to 'x'. Since 'x' is a pointer itself, either pass a pointer to pointer, or pass a reference to pointer.
    Code:
    void foo(int **pLocal)  // pointer to pointer
    {
       *pLocal = new int [10];
    }
    
    int main()
    {
        int *p=NULL;
        foo( &p );
    }
    or
    Code:
    void foo(int *& pLocal)  // reference to pointer
    {
       pLocal = new int [10];
    }
    
    int main()
    {
        int *p=NULL;
        foo( p );
    }
    Regards,

    Paul McKenzie

  5. #5
    Join Date
    Oct 2005
    Posts
    6

    Re: Passing array of struct as reference

    The first code: void foo(int **pLocal) crushes, though, the second code:
    void foo(int *& pLocal) works well in .cpp file but doesn't pass compilation in a .c file.
    error C2143: syntax error : missing ')' before '&'
    error C2143: syntax error : missing '{' before '&'
    error C2059: syntax error : '&'
    error C2059: syntax error : ')'

    Thanks
    Eli

  6. #6
    Join Date
    Feb 2002
    Posts
    4,640

    Re: Passing array of struct as reference

    Are you writing a C or C++ program?

    Viggy

  7. #7
    Join Date
    Feb 2005
    Location
    Normandy in France
    Posts
    4,590

    Re: Passing array of struct as reference

    Quote Originally Posted by elireu
    The first code: void foo(int **pLocal) crushes, though, the second code:
    What is the exact code you used?
    Are you sure to have correctly assigned the *pLocal pointer, like that:
    Code:
    *pLocal=MyArrayPtr;
    And not like that:
    Code:
    pLocal=MyArrayPtr; // incorrect - and will at least generate a compilation warning for a C++ compiler!
    "inherit to be reused by code that uses the base class, not to reuse base class code", Sutter and Alexandrescu, C++ Coding Standards.
    Club of lovers of the C++ typecasts cute syntax: Only recorded member.

    Out of memory happens! Handle it properly!
    Say no to g_new()!

  8. #8
    Join Date
    Oct 2005
    Posts
    6

    Re: Passing array of struct as reference

    I'm writing "C" and compiling with VC 6. The following code passes compilation but crushes in run time.

    Thanks, Eli
    ---------------------------
    #include <stdio.h>
    #include <malloc.h>

    typedef struct
    {
    char name[80];
    int id;
    }MyStruct;

    int MyFunc(MyStruct **MyPtr);

    void main()
    {
    int i;

    MyStruct *MyPtr = NULL;

    MyFunc(&MyPtr);

    for(i=0;i<100;i++)
    {
    printf("Name: %s, id: %d\n",MyPtr[i].name, MyPtr[i].id );
    }
    free(MyPtr);

    }

    int MyFunc(MyStruct **MyArrayPtr)
    {
    int i;

    *MyArrayPtr = malloc(sizeof(MyStruct)*100);

    for(i=0;i<100;i++)
    {
    MyArrayPtr[i]->id = i;
    sprintf(MyArrayPtr[i]->name, "Eli-%d", i);
    }
    return 0;
    }

  9. #9
    Join Date
    Sep 2004
    Posts
    561

    Re: Passing array of struct as reference

    Use this one.

    Code:
    #include <stdio.h>
    #include <malloc.h>
    typedef struct
    {
    char name[80];
    int id;
    }MyStruct;
     
    int MyFunc(MyStruct *&MyArrayPtr)  
    {
    int i;
    MyArrayPtr = (MyStruct*) malloc(sizeof(MyStruct)*100);
    for(i=0;i<100;i++)
    {
    MyArrayPtr[i].id = i;
    sprintf(MyArrayPtr[i].name, "Eli-%d", i);
    }
    return 0;
    }
    
    int main()
    {
    int i;
    MyStruct *MyPtr = NULL;
    MyFunc(MyPtr);
    for(i=0;i<100;i++)
    {
    printf("Name: %s, id: %d\n",MyPtr[i].name, MyPtr[i].id );
    }
    free(MyPtr);
    return 0;
    }

  10. #10
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Passing array of struct as reference

    First, it's int main() not void main().

    Second, assuming T is a type, the reason why it crashes is that you cannot process a passed in T** as an array type using [] without all the information about the underlying T*. This is one of the pitfalls that C and C++ programmers come acrosss, and that is believing that a function can handle all the pointer indirections safely when passed a T** or T***, or T****, etc. without further information. The only thing that is guaranteed to work is when you pass a T* (single indirection). References are different animals, which is why they work.

    When you pass a T**, you're passing only a pointer. The calling function has no information beyond this (it doesn't know the T* part of T**, i.e. number of elements). The called function only knows about T**, but within the called function, you are accessing it as if it also knows about T* in your loop.

    So the only thing you can do is to create the pointer and pass it back to the caller. Don't try to access it using [] within the calling function.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; October 12th, 2005 at 01:04 PM.

  11. #11
    Join Date
    Oct 2005
    Posts
    6

    Re: Passing array of struct as reference

    Eventually, I got this code working. Is it safe enough ?
    Thanks, Eli
    ------------------------
    #include <stdio.h>
    #include <malloc.h>

    typedef struct
    {
    char name[80];
    int id;
    }MyStruct;

    int MyFunc(MyStruct **ArrayPtr);

    void main()
    {
    int i;

    MyStruct *MyPtr = NULL;

    MyFunc(&MyPtr);

    for(i=0;i<100;i++)
    {
    printf("Name: %s, id: %d\n",MyPtr[i].name, MyPtr[i].id );
    }
    free(MyPtr);

    }

    int MyFunc(MyStruct **ArrayPtr)
    {
    int i;
    MyStruct *MyArrayPtr;

    MyArrayPtr = malloc(sizeof(MyStruct)*100);

    for(i=0;i<100;i++)
    {
    MyArrayPtr[i].id = i;
    sprintf(MyArrayPtr[i].name, "Eli-%d", i);
    }
    *ArrayPtr = MyArrayPtr;
    return 0;
    }

  12. #12
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Passing array of struct as reference

    Yes, this should work. Also, please use code tags when posting. All of your code is aligned on the left side of the page, making it very difficult to read what you've posted.

    The difference in your second version is that you are creating the data "from scratch" from a local MyStruct*, and then explicitly assigning the pointer passed in to the allocated memory that the local pointer is pointing to. You are not creating it from the passed in MyStruct** (which as I stated, the called function is clueless about the underlying MyStruct* when passed a MyStruct**).

    Regards,

    Paul McKenzie

  13. #13
    Join Date
    Oct 2005
    Posts
    6

    Re: Passing array of struct as reference

    I just copy and past my code and it looks well aligned. what do you mean by 'code tags' ?

    Thanks very much for the help
    Eli

  14. #14
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Passing array of struct as reference

    Quote Originally Posted by elireu
    I just copy and past my code and it looks well aligned. what do you mean by 'code tags' ?

    Thanks very much for the help
    Eli
    Here is your original code:

    #include <stdio.h>
    #include <malloc.h>

    typedef struct
    {
    char name[80];
    int id;
    }MyStruct;

    int MyFunc(MyStruct **ArrayPtr);

    void main()
    {
    int i;

    MyStruct *MyPtr = NULL;

    MyFunc(&MyPtr);

    for(i=0;i<100;i++)
    {
    printf("Name: %s, id: %d\n",MyPtr[i].name, MyPtr[i].id );
    }
    free(MyPtr);

    }

    Now look at this:
    Code:
    #include <stdio.h>
    #include <malloc.h>
    
    typedef struct
    {
        char name[80];
        int id;
    }MyStruct;
    
    int MyFunc(MyStruct **ArrayPtr);
    
    void main()
    {
        int i;
    
        MyStruct *MyPtr = NULL;
    
        MyFunc(&MyPtr);
    
        for (i=0;i<100;i++)
        {
            printf("Name: %s, id: %d\n",MyPtr[i].name, MyPtr[i].id );
        }
        free(MyPtr);
    }
    See the difference? The way you use code tags is to enclose your code in

    [ c o d e ] and [ / c o d e ] blocks (remove the spaces).

    Regards,

    Paul McKenzie

  15. #15
    Join Date
    Feb 2005
    Location
    Normandy in France
    Posts
    4,590

    Re: Passing array of struct as reference

    Quote Originally Posted by elireu
    MyArrayPtr[i]->id = i;
    sprintf(MyArrayPtr[i]->name, "Eli-%d", i);
    Here is the bug!
    MyArrayPtr is a valid block of 4 bytes which is a pointer to the malloced block.
    So, (*MyArrayPtr) is valid, but MyArrayPtr[i] is invalid for i>0
    In fact, you use MyArrayPtr like if it was a pointer to an array of pointers to structs, but it is a pointer to a pointer to an array of structs.

    The correct code is:
    [code]
    (*MyArrayPtr)[i].id = i;
    sprintf((*MyArrayPtr)[i].name, "Eli-%d", i);
    [code]
    It is just some basic pointer arithmetic : dereferencing then indexing, is not the same that indexing then dereferencing.

    However your new code:
    Code:
    int MyFunc(MyStruct **ArrayPtr)
    {
    int i;
    MyStruct *MyArrayPtr;
    
    MyArrayPtr = malloc(sizeof(MyStruct)*100);
    
    for(i=0;i<100;i++)
    {
    MyArrayPtr[i].id = i;
    sprintf(MyArrayPtr[i].name, "Eli-%d", i);
    }
    *ArrayPtr = MyArrayPtr;
    return 0;
    }
    • Works perfectly, and is easier to write and read for non-experienced programmers.
    • Is easier to optimize for the compiler, so it will probably run faster.
    "inherit to be reused by code that uses the base class, not to reuse base class code", Sutter and Alexandrescu, C++ Coding Standards.
    Club of lovers of the C++ typecasts cute syntax: Only recorded member.

    Out of memory happens! Handle it properly!
    Say no to g_new()!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured