Problem with an array of pointers

R

Rob Thorpe

I have a set of data structures that are collected together in array.
This array is in turn packaged in a struct itself. The structs look
like this:-

struct index_entry_t
{
char *id;
char *description;
};
typedef struct index_entry_t index_entry_t;

struct index_t
{
int no_of_entries;
index_entry_t *table[];
};
typedef struct index_t index_t;

The member 'table' of index_t contains an array of pointers to
index_entry_t's.

The program then goes on to make a pointer to an index_t. The result
is shown below:-
_____________
i ------>|index_t |
|_____________|
|no_of_entries|
|_____________|
|table | _______ _____________
|____________--------->| ----------------->|index_entry_t|
|_______| |_____________|
| ----------> |id |
|_______| |_____________|
| ----------> |description |
|_______| |_____________|
| ... |

My problem is, I can't find the right syntax to access the members, ie
the index_entry_t's.

To me these seem the right ways:

(i->table[n])->id
or
*(i->table[n]).id

but they both give the error:
test_ind2.c:86: error: request for member `description' in something
not a structure or union

on my compiler (gcc).

What is wrong?
 
P

pete

Rob said:
I have a set of data structures that are collected together in array.
This array is in turn packaged in a struct itself. The structs look
like this:-

struct index_entry_t
{
char *id;
char *description;
};
typedef struct index_entry_t index_entry_t;

struct index_t
{
int no_of_entries;
index_entry_t *table[];
};
typedef struct index_t index_t;

This line:
index_entry_t *table[];
is not standard C.
 
M

Martin Ambuhl

pete said:
Rob said:
I have a set of data structures that are collected together in array.
This array is in turn packaged in a struct itself. The structs look
like this:-

struct index_entry_t
{
char *id;
char *description;
};
typedef struct index_entry_t index_entry_t;

struct index_t
{
int no_of_entries;
index_entry_t *table[];
};
typedef struct index_t index_t;


This line:
index_entry_t *table[];
is not standard C.

And why do you say this? Has the current standard been repealed? Have
flexible array members been removed from the standard?
 
O

Old Wolf

pete said:
Rob said:
I have a set of data structures that are collected together in array.
This array is in turn packaged in a struct itself. The structs look
like this:-

struct index_entry_t
{
char *id;
char *description;
};
typedef struct index_entry_t index_entry_t;

struct index_t
{
int no_of_entries;
index_entry_t *table[];
};
typedef struct index_t index_t;

This line:
index_entry_t *table[];
is not standard C.

It's a flexible array member (N869 6.7.2.1#15)
This was introduced in ISO 9899:1999 as a legal alternative
to the 'struct hack'.

To the OP: the code compiles without error for me (using
gcc 3.4.2 in C99 mode), can you post the exact code that
gives the problem? My code was:

int main(void)
{
struct index_t *i;
i->table[4]->id;
}
 
B

Barry Schwarz

I have a set of data structures that are collected together in array.
This array is in turn packaged in a struct itself. The structs look
like this:-

struct index_entry_t
{
char *id;
char *description;
};
typedef struct index_entry_t index_entry_t;

struct index_t
{
int no_of_entries;
index_entry_t *table[];

Obviously in your real code there is some value specified for the
array size.
};
typedef struct index_t index_t;

The member 'table' of index_t contains an array of pointers to
index_entry_t's.

The program then goes on to make a pointer to an index_t. The result
is shown below:-

snip diagram
My problem is, I can't find the right syntax to access the members, ie
the index_entry_t's.

To me these seem the right ways:

(i->table[n])->id

This is correct but the parentheses are unnecessary.
or
*(i->table[n]).id

This is not correct since . has higher precedence than *. You need
(*i->table[n]).id
but they both give the error:
test_ind2.c:86: error: request for member `description' in something
not a structure or union

This error must be for a different line of code since the description
member is not referenced in either.
on my compiler (gcc).

What is wrong?

Post the real code. Preferably a small complete compilable example
that demonstrates the problem.


<<Remove the del for email>>
 
R

Rob Thorpe

pete said:
Rob said:
I have a set of data structures that are collected together in array.
This array is in turn packaged in a struct itself. The structs look
like this:-

struct index_entry_t
{
char *id;
char *description;
};
typedef struct index_entry_t index_entry_t;

struct index_t
{
int no_of_entries;
index_entry_t *table[];
};
typedef struct index_t index_t;

This line:
index_entry_t *table[];
is not standard C.

It's a flexible array member (N869 6.7.2.1#15)
This was introduced in ISO 9899:1999 as a legal alternative
to the 'struct hack'.

Aha, this construct is only legal C99. Unfortunately, my code must
work on a C90 or C++ compiler.

It seems to make perfect sense to write "index_entry_t *table[];",
after all I want a pointer to an array of index_entry_t's and I want
the pointer named table. The new standard makes more sense than the
old on this point.

If I replace this with index_entry_t **table; it works.
To the OP: the code compiles without error for me (using
gcc 3.4.2 in C99 mode), can you post the exact code that
gives the problem? My code was:

int main(void)
{
struct index_t *i;
i->table[4]->id;
}

Thanks to everyone who posted.
 
J

John Bode

I have a set of data structures that are collected together in array.
This array is in turn packaged in a struct itself. The structs look
like this:-

struct index_entry_t
{
char *id;
char *description;
};
typedef struct index_entry_t index_entry_t;

struct index_t
{
int no_of_entries;
index_entry_t *table[];
};
typedef struct index_t index_t;

[snip diagram]
My problem is, I can't find the right syntax to access the members, ie
the index_entry_t's.

To me these seem the right ways:

(i->table[n])->id
or
*(i->table[n]).id

but they both give the error:
test_ind2.c:86: error: request for member `description' in something
not a structure or union

on my compiler (gcc).

What is wrong?


Two questions:

1. Which version of gcc?
2. Are you sure you have the right statement for the error?

The first form should work just fine (type of i->table[n] should be
index_entry_t *), unless I've missed something. The second is wrong,
it should be (*i->table[n]).id (remember, x->y is equivalent to
(*x).y, not *(x).y).
 
O

Old Wolf

Rob Thorpe wrote:

struct index_t
{
int no_of_entries;
index_entry_t *table[];
};
typedef struct index_t index_t;

It seems to make perfect sense to write "index_entry_t *table[];",
after all I want a pointer to an array of index_entry_t's and I want
the pointer named table.

In a declaration, square brackets indicate an array.
The star indicates a pointer.
When both are combined in this case, the square brackets
have precedence; the original 'table' is an array of
pointers, not a pointer-to-array.
If I replace this with index_entry_t **table; it works.

Naturally. This declares a pointer (which you can then
point to the first member of an array).

Read through chapter 6 of the FAQ if you haven't already (you
may find a few useful tidbits you didn't already know).
The new standard makes more sense than the old on this point.

I'm not sure that it does what you think it does; it declares
an array of pointers, where the size of the array is unknown.
The only correct way to allocate a struct like this is:

struct index_t *ptr = malloc(sizeof (struct index_t)
+ sizeof(index_entry_t *) * N);

and then you can access ptr->table[0], ptr->table[1],
and so on, up to ptr->table[N-1] safely.

In C90 it wasn't possible to have a structure that
contained an array whose size wasn't known until runtime.
The common workaround was called the 'struct hack':
basically the same as what we just did, execpt that the
array member was declared as
index_entry_t *table[1];
and you would go ahead an access table[2] etc. anyway.
 
R

Rob Thorpe

Rob Thorpe wrote:

struct index_t
{
int no_of_entries;
index_entry_t *table[];
};
typedef struct index_t index_t;

It seems to make perfect sense to write "index_entry_t *table[];",
after all I want a pointer to an array of index_entry_t's and I want
the pointer named table.

In a declaration, square brackets indicate an array.
The star indicates a pointer.
When both are combined in this case, the square brackets
have precedence; the original 'table' is an array of
pointers, not a pointer-to-array.

That's what I meant, when I coded it, I forgot and confused myself in
the time since. The reasons of the error seems obvious now.
Naturally. This declares a pointer (which you can then
point to the first member of an array).

Read through chapter 6 of the FAQ if you haven't already (you
may find a few useful tidbits you didn't already know).

That's just what I've been doing in the past couple of days,
interesting reading.
The new standard makes more sense than the old on this point.

I'm not sure that it does what you think it does; it declares
an array of pointers, where the size of the array is unknown.
The only correct way to allocate a struct like this is:

struct index_t *ptr = malloc(sizeof (struct index_t)
+ sizeof(index_entry_t *) * N);

and then you can access ptr->table[0], ptr->table[1],
and so on, up to ptr->table[N-1] safely.

I see. That's not what I want since I can't tell how many
index_entry_t's there will be when I initialise the index_t. I need
to malloc 'table' separately.
In C90 it wasn't possible to have a structure that
contained an array whose size wasn't known until runtime.
The common workaround was called the 'struct hack':
basically the same as what we just did, execpt that the
array member was declared as
index_entry_t *table[1];
and you would go ahead an access table[2] etc. anyway.

I read about this, but never understood why anyone would want to do
it, I get it now, though it looks best avoided.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top