Zero-sized array

This has nothing to do with SDL, but a lot to do with cross-platform (or
in this case cross-compiler) development. I’m working on a program on
Win32 that has data with this type of construct:

struct thingy {
int header1;
char header2[6];
int length_of_data;
char data[];
};

“thingy” is an object with a 14-byte header, and a data payload of
indeterminite size. (But the program knows to check length_of_data to
find out how long “data” is.) The convenience is I can access the payload
by doing instance_of_thingy->data, and it works. I’ve been doing this for
years. Under Borland compilers for DOS, this works with no problem. Same
with WATCOM for DOS and Win32. DevStudio complains about it, but works
properly. GCC and CodeWarrior simply choke on it. Is there a safe way to
do this? Ideally, sizeof(thingy)==14. Or do I have to just rewrite all
my code?

-Chuck

This has nothing to do with SDL, but a lot to do with cross-platform (or
in this case cross-compiler) development. I’m working on a program on
Win32 that has data with this type of construct:

struct thingy {
int header1;
char header2[6];
int length_of_data;
char data[];
};

“thingy” is an object with a 14-byte header, and a data payload of
indeterminite size. (But the program knows to check length_of_data to
find out how long “data” is.) The convenience is I can access the payload
by doing instance_of_thingy->data, and it works. I’ve been doing this for
years. Under Borland compilers for DOS, this works with no problem. Same
with WATCOM for DOS and Win32. DevStudio complains about it, but works
properly. GCC and CodeWarrior simply choke on it. Is there a safe way to
do this? Ideally, sizeof(thingy)==14. Or do I have to just rewrite all
my code?

Does char data[0] work?

egcs handles this and gives sizeof(thingy)==16 (padded out to word boundaries)

-Sam Lantinga				(slouken at devolution.com)

Lead Programmer, Loki Entertainment Software–
Author of Simple DirectMedia Layer -
http://www.devolution.com/~slouken/SDL/

Does char data[0] work?

egcs handles this and gives sizeof(thingy)==16 (padded out to word boundaries)

No, I guess I forgot to mention I tried that, hence the subject. CW
complaines that the “data type is incomplete”, as if I tried to
instantiate an undefined class, or something. data[1] works just fine,
though, except all my code that uses it crashes immediately. (The sizeof
thing.) I could go through all the code and change the way it works, but
that would be extraordinarily time-consuming, and what would I change it
to? Doing it this way is just too easy.

-Chuck

Chuck Homic writes:

Does char data[0] work?

egcs handles this and gives sizeof(thingy)==16 (padded out to word boundaries)

No, I guess I forgot to mention I tried that, hence the subject. CW
complaines that the “data type is incomplete”, as if I tried to
instantiate an undefined class, or something. data[1] works just fine,
though, except all my code that uses it crashes immediately. (The sizeof
thing.) I could go through all the code and change the way it works, but
that would be extraordinarily time-consuming, and what would I change it
to? Doing it this way is just too easy.

Just use char *data, it is the same as char data[] .

Phil

0-length arrays are disallowed by ANSI C put permitted as a gcc
extension.

If you really really really want sizeof your struct to be 14 bytes
(why do you care?), and you’re prepared to eat the performance cost of
having them be misaligned if you have an array of them, etc. then you
can use gcc’s attribute((packed)) on the struct fields to pack
them together tightly regardless of alignment. That should give you
the size you want.

Normally C programmers use 1-element arrays at the end of structs to
achieve the “variable-sized array” effect and then subtract that off
when doing size computations.

-Mat

Just use char *data, it is the same as char data[] .

Not exactly. char data[] is located, and points to, exactly the end of my
structure, and takes up no space. char *data is an uninitialized pointer,
which does take up space, and can’t be used to access data at that
location. (And if it did, it would overwrite itself anyway!)

-ChuckOn Wed, 24 Mar 1999, Lavoie Philippe wrote:

Chuck Homic writes:> On Wed, 24 Mar 1999, Lavoie Philippe wrote:

Just use char *data, it is the same as char data[] .

Not exactly. char data[] is located, and points to, exactly the end of my
structure, and takes up no space. char *data is an uninitialized pointer,
which does take up space, and can’t be used to access data at that
location. (And if it did, it would overwrite itself anyway!)

Oh, got it. But like the Mat said, data[] is an invalid ANSI
construct. If you want to use that with an ANSI compiler, you will
need to change your construct.

Phil

Oh, got it. But like the Mat said, data[] is an invalid ANSI
construct. If you want to use that with an ANSI compiler, you will
need to change your construct.

Yeah, I guess I’m going to have to grep for sizeof and just handle it. I
was hoping to avoid it, though. That’s 2 megs of code to wade through. :frowning:

-Chuck

Lavoie Philippe wrote:

Just use char *data, it is the same as char data[] .

Nope. sizeof( char* ) is not equal to sizeof( char[0] ).

m.–
“We can deny everything, except that we have the possibility of being better.
Simply reflect on that.”
– His Holiness The Dalai Lama

Lavoie Philippe wrote:

Just use char *data, it is the same as char data[] .

Nope. sizeof( char* ) is not equal to sizeof( char[0] ).

actually, ‘sizeof(char *)’ is equal to ‘sizeof(int)’, at least on Intel
machines.On Wed, 24 Mar 1999, Michael K Vance wrote:

m.


“We can deny everything, except that we have the possibility of being better.
Simply reflect on that.”
– His Holiness The Dalai Lama


Scott M. Stone
Head of TurboLinux English / Systems Administrator
Pacific HiTech, Inc. (http://www.turbolinux.com)

Looks like I solved my own problem. CodeWarrior was acting a bit funny,
because although my zero-sized array was the last data in the class
definition, it wasn’t the last thing. If I move it right before the
closing brace, it compiles just fine, assuming the “Strict ANSI” switch is
off. Sorry to waste everyone’s time.

-Chuck

Sorry if this seems obvious, but I’d like to get more information if I
could. From what you’ve written, I don’t see why you can’t use char
*data. You could use *alloc to stuff the payload into
instance_of_thingy->data and still use length_of_data to tell how long
it is. It will make (sizeof(thingy) > 14) however.On 24 Mar, Chuck Homic wrote:

This has nothing to do with SDL, but a lot to do with cross-platform (or
in this case cross-compiler) development. I’m working on a program on
Win32 that has data with this type of construct:

struct thingy {
int header1;
char header2[6];
int length_of_data;
char data[];
};

“thingy” is an object with a 14-byte header, and a data payload of
indeterminite size. (But the program knows to check length_of_data to
find out how long “data” is.) The convenience is I can access the payload
by doing instance_of_thingy->data, and it works. I’ve been doing this for
years. Under Borland compilers for DOS, this works with no problem. Same
with WATCOM for DOS and Win32. DevStudio complains about it, but works
properly. GCC and CodeWarrior simply choke on it. Is there a safe way to
do this? Ideally, sizeof(thingy)==14. Or do I have to just rewrite all
my code?


| |/ | | | _ | | | mailto:@Knight_Walker |
| / | / / | | http://www.aros.net/~kwalker |
| \ | ___ | | |
| |\ | | / \ | | The Kobran Imperium (801)265-1299 |
|| || || || _____________________________________/

If that works, then “attribute((PACKED))” at the end of each line
in the typedef {} to remove the padding.

-BenOn 24 Mar, Sam Lantinga wrote:

Does char data[0] work?

egcs handles this and gives sizeof(thingy)==16 (padded out to word boundaries)

-Sam Lantinga (slouken at devolution.com)


| |/ | | | _ | | | mailto:@Knight_Walker |
| / | / / | | http://www.aros.net/~kwalker |
| \ | ___ | | |
| |\ | | / \ | | The Kobran Imperium (801)265-1299 |
|| || || || _____________________________________/

Yeah, I guess I’m going to have to grep for sizeof and just handle it. I
was hoping to avoid it, though. That’s 2 megs of code to wade through. :frowning:

If it’s just sizeof(thingy) it shouldn’t matter because re-compiling it
will cause sizeof() will return the new size. You may need to write a
conversion program if you have data structures that are written with
the old format.On 24 Mar, Chuck Homic wrote:


| |/ | | | _ | | | mailto:@Knight_Walker |
| / | / / | | http://www.aros.net/~kwalker |
| \ | ___ | | |
| |\ | | / \ | | The Kobran Imperium (801)265-1299 |
|| || || || _____________________________________/

actually, ‘sizeof(char *)’ is equal to ‘sizeof(int)’, at least on Intel
machines.

Actually, sizeof(char *) is a 32-bit storage type on Intel machines
(Just about any pointer is), so is sizeof(int). It’s just coincidence.On 24 Mar, Scott Stone wrote:


| |/ | | | _ | | | mailto:@Knight_Walker |
| / | / / | | http://www.aros.net/~kwalker |
| \ | ___ | | |
| |\ | | / \ | | The Kobran Imperium (801)265-1299 |
|| || || || _____________________________________/