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;
}
Re: Passing array of struct as reference
[ redirected ]
Regards,
Siddhartha
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
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
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
Re: Passing array of struct as reference
Are you writing a C or C++ program?
Viggy
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!
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;
}
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;
}
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
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;
}
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
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
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
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.