D
DSF
Hello,
My desire is to pass an array of structures, created within the
called function, back through one of its parameters.
I have had no problem doing this with arrays of strings, which I
would think is more difficult. You start with a pointer to a pointer
of arrays **strings, and then pass the address of **strings, to the
function so the function takes parameters like char ***string. But I
did get that to work.
I've found doing the same thing with an array of structs to be more
difficult. I feel I'm missing the obvious. The string example above
returns an array of pointers because each pointer is pointing to a
different string, since the strings vary in length. In an array of
structs, each structure is the same size. So there is no need for
that level of indirection.
A memory allocation of sizeof(struct) * numberofstructs is all that
is needed/desired.
Of course, there is a FreeAlternateStreams function to free the
names and the struct array!
It works properly when I use a proxy pointer (*ds) to build the
array. I then assign the proxy pointer to the start of the array to
*sd, which assigns it back to the calling function.
It seems I could just use *sd and eliminate the proxy, but when I do
that, *sd points to an array of pointers to struct instead of the
start of the structure.
The code below works when VERSION1 is defined (proxy *ds). It is an
example written purely for this message. There is no error checking
on malloc for clarity's sake.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tag_streamdata
{
char *name;
int size;
int attr;
}streamdata;
int GetAlternateStreams(streamdata **sd);
#define VERSION1
int main()
{
streamdata *sd;
int n = 0;
GetAlternateStreams(&sd);
while(sd[n].name != NULL)
{
printf("Name: %s\n", sd[n].name);
n++;
}
return EXIT_SUCCESS;
}
#ifdef VERSION1
int GetAlternateStreams(streamdata **sd)
{
char *names[] = {"name1", "name2", "name3"};
int nameidx = 0;
/* tds is a temp for realloc failure*/
streamdata *tsd, *ds;
int i;
int numstreams = 0;
ds = NULL;
for(i = 0; i < 3; i++)
{
tsd = realloc(ds, sizeof(streamdata) * (numstreams+2));
ds = tsd;
ds[numstreams].name = malloc(strlen(names[nameidx])+1);
strcpy(ds[numstreams].name, names[nameidx++]);
ds[numstreams].size = 4;
ds[numstreams].attr = 3;
numstreams++;
/* A NULL name member marks the end of the array */
ds[numstreams].name = NULL;
*sd = ds;
}
return 0;
}
#else
/* I would think that ds could be replaced with *sd, which would de
reference it back to the calling function's *sd, but I can't get it to
work. When I use the above code, sd[0] is the first structure, sd[1]
is located sizeof(streamdata) away from sd[0], a nice linear array.
In the following code sd[1] is 4 bytes away from sd[0], it's
creating an array of pointers instead of structs. I'm sure *sd below
can be made to work without the proxy *ds, but I can't seem to get the
syntax correct so that I get a pointer to the first element of an
array of structures, not an array of pointer to structures.
*/
int GetAlternateStreams(streamdata **sd)
{
char *names[] = {"name1", "name2", "name3"};
int nameidx = 0;
streamdata *tsd;
int i;
int numstreams = 0;
*sd = NULL;
/* This section simplifies data entry that is much more complicated */
for(i = 0; i < 3; i++)
{
tsd = realloc(*sd, sizeof(streamdata) * (numstreams+2));
*sd = tsd;
(*sd)[numstreams].name = malloc(strlen(names[nameidx])+1);
strcpy((*sd)[numstreams].name, names[nameidx++]);
(*sd)[numstreams].size = 4;
(*sd)[numstreams].attr = 3;
numstreams++;
/* A NULL name member marks the end of the array */
(*sd)[numstreams].name = NULL;
/* Note that I have also used (*sd[numstreams).name with the same
results */
}
return 0;
}
#endif
There has to be something simple I'm missing. **sd dereferenced by
*sd[element] should be the same as *ds dereferenced by ds[element],
but it's not. I think it relates to the * in *sd[element] indicating
an array of pointers, but I'm not sure how.
Thanks for any help!
DSF
My desire is to pass an array of structures, created within the
called function, back through one of its parameters.
I have had no problem doing this with arrays of strings, which I
would think is more difficult. You start with a pointer to a pointer
of arrays **strings, and then pass the address of **strings, to the
function so the function takes parameters like char ***string. But I
did get that to work.
I've found doing the same thing with an array of structs to be more
difficult. I feel I'm missing the obvious. The string example above
returns an array of pointers because each pointer is pointing to a
different string, since the strings vary in length. In an array of
structs, each structure is the same size. So there is no need for
that level of indirection.
A memory allocation of sizeof(struct) * numberofstructs is all that
is needed/desired.
Of course, there is a FreeAlternateStreams function to free the
names and the struct array!
It works properly when I use a proxy pointer (*ds) to build the
array. I then assign the proxy pointer to the start of the array to
*sd, which assigns it back to the calling function.
It seems I could just use *sd and eliminate the proxy, but when I do
that, *sd points to an array of pointers to struct instead of the
start of the structure.
The code below works when VERSION1 is defined (proxy *ds). It is an
example written purely for this message. There is no error checking
on malloc for clarity's sake.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tag_streamdata
{
char *name;
int size;
int attr;
}streamdata;
int GetAlternateStreams(streamdata **sd);
#define VERSION1
int main()
{
streamdata *sd;
int n = 0;
GetAlternateStreams(&sd);
while(sd[n].name != NULL)
{
printf("Name: %s\n", sd[n].name);
n++;
}
return EXIT_SUCCESS;
}
#ifdef VERSION1
int GetAlternateStreams(streamdata **sd)
{
char *names[] = {"name1", "name2", "name3"};
int nameidx = 0;
/* tds is a temp for realloc failure*/
streamdata *tsd, *ds;
int i;
int numstreams = 0;
ds = NULL;
for(i = 0; i < 3; i++)
{
tsd = realloc(ds, sizeof(streamdata) * (numstreams+2));
ds = tsd;
ds[numstreams].name = malloc(strlen(names[nameidx])+1);
strcpy(ds[numstreams].name, names[nameidx++]);
ds[numstreams].size = 4;
ds[numstreams].attr = 3;
numstreams++;
/* A NULL name member marks the end of the array */
ds[numstreams].name = NULL;
*sd = ds;
}
return 0;
}
#else
/* I would think that ds could be replaced with *sd, which would de
reference it back to the calling function's *sd, but I can't get it to
work. When I use the above code, sd[0] is the first structure, sd[1]
is located sizeof(streamdata) away from sd[0], a nice linear array.
In the following code sd[1] is 4 bytes away from sd[0], it's
creating an array of pointers instead of structs. I'm sure *sd below
can be made to work without the proxy *ds, but I can't seem to get the
syntax correct so that I get a pointer to the first element of an
array of structures, not an array of pointer to structures.
*/
int GetAlternateStreams(streamdata **sd)
{
char *names[] = {"name1", "name2", "name3"};
int nameidx = 0;
streamdata *tsd;
int i;
int numstreams = 0;
*sd = NULL;
/* This section simplifies data entry that is much more complicated */
for(i = 0; i < 3; i++)
{
tsd = realloc(*sd, sizeof(streamdata) * (numstreams+2));
*sd = tsd;
(*sd)[numstreams].name = malloc(strlen(names[nameidx])+1);
strcpy((*sd)[numstreams].name, names[nameidx++]);
(*sd)[numstreams].size = 4;
(*sd)[numstreams].attr = 3;
numstreams++;
/* A NULL name member marks the end of the array */
(*sd)[numstreams].name = NULL;
/* Note that I have also used (*sd[numstreams).name with the same
results */
}
return 0;
}
#endif
There has to be something simple I'm missing. **sd dereferenced by
*sd[element] should be the same as *ds dereferenced by ds[element],
but it's not. I think it relates to the * in *sd[element] indicating
an array of pointers, but I'm not sure how.
Thanks for any help!
DSF