Reading from file into struct array / memory layout

E

eriwik

Hi,

I'm working on a small application which processes PNG-images and need
to read parts of them into structures and/or variables and I was
wondering what assumptions one can make about how the compiler places
things in memory.

Or more specific, I want to read the color-palette into a array of
structs with the following format:

typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
} palette8e;

and the array:

typedef palette8e palette8[256];

Can I assume that a pointer to a palette8 will be a block of 3*256
consecutive bytes in memory so that I can just read in from the file
(which stores the palette as 256 tripplets of bytes)?

If not, is there some other easy way to do this, except for reading the
file byte for byte?
 
R

Roger Leigh

Or more specific, I want to read the color-palette into a array of
structs with the following format:

typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
} palette8e;

and the array:

typedef palette8e palette8[256];

Can I assume that a pointer to a palette8 will be a block of 3*256
consecutive bytes in memory so that I can just read in from the file
(which stores the palette as 256 tripplets of bytes)?

#include <stdio.h>
#include <stdint.h>

typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
} palette8e;

typedef palette8e palette8[256];

int main(void)
{
palette8 pal;


for (int i=0; i<10; ++i)
printf("pal[%d] r=%p g=%p b=%p\n", i, &pal.red, &pal.green, &pal.blue);
}

It looks like it works, at least on my platform
(ppc-unknown-linux-gnu). It's not truly portable, though.
 
L

Lawrence Kirby

Hi,

I'm working on a small application which processes PNG-images and need
to read parts of them into structures and/or variables and I was
wondering what assumptions one can make about how the compiler places
things in memory.

Or more specific, I want to read the color-palette into a array of
structs with the following format:

typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
} palette8e;

and the array:

typedef palette8e palette8[256];

Can I assume that a pointer to a palette8 will be a block of 3*256
consecutive bytes in memory so that I can just read in from the file
(which stores the palette as 256 tripplets of bytes)?

C allows there to be padding between structure members and after the last
member so you can't assume that in general. A compiler might for example
add a trailing byte of padding to bring the size of the structure up toi 4
bytes, if the architecture can handle 4 byte operation efficiently.
If not, is there some other easy way to do this, except for reading the
file byte for byte?

You could use an array instead:

enum ( PAL_RED, PAL_GREEN, PAL_BLUE };

typedef uint8_t palette8e[3];

typedef palette8e palette8[256];


And then you could use for example

palette8 pal;
....
green = pal[ind][PAL_GREEN];

There is never padding between array elements.

Lawrence
 
S

SM Ryan

# Can I assume that a pointer to a palette8 will be a block of 3*256
# consecutive bytes in memory so that I can just read in from the file
# (which stores the palette as 256 tripplets of bytes)?

No.

The safest way to read structures is to read the individual fields.
That way you can completely control packing and endian issues.

# If not, is there some other easy way to do this, except for reading the
# file byte for byte?

There's no easy and safe alternative in ANSI C. Some dialects do let
you control structure packing.
 
M

Me

Or more specific, I want to read the color-palette into a array of
structs with the following format:

typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
} palette8e;

and the array:

typedef palette8e palette8[256];

Can I assume that a pointer to a palette8 will be a block of 3*256
consecutive bytes in memory so that I can just read in from the file
(which stores the palette as 256 tripplets of bytes)?

You can assume it but it may not be portable:

6.7.2.1/13 "There may be unnamed padding within a structure object, but
not at its beginning."
6.7.2.1/15 "There may be unnamed padding at the end of a structure or
union."
If not, is there some other easy way to do this, except for reading the
file byte for byte?

If you're willing to sacrifice non-portability, you can assume it's
true (if it actually is true) or you can see if your compiler offers
any method to control padding/alignment of a struct. Otherwise you're
either going to have to read in byte by byte or convert this to a plain
array of uint8_t's.
 
M

Malcolm

typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
} palette8e;

and the array:

typedef palette8e palette8[256];

Can I assume that a pointer to a palette8 will be a block of 3*256
consecutive bytes in memory so that I can just read in from the file
(which stores the palette as 256 tripplets of bytes)?

If not, is there some other easy way to do this, except for reading the
file byte for byte?

What's your problem?

void loadpalette(palette8e *pal, int N, FILE *fp)
{
int i;

for(i=0;i<N;i++)
{
pal.red = fgetc(fp);
pal.green = fgetc(fp);
pal.blue = fgetc(fp);
}
}

This is hardly difficult code. Also, if for some reason you want to add
alpha to the palette of reverse the channel order, this approach is easilyt
modifiable.
 
E

eriwik

Malcolm said:
What's your problem?

void loadpalette(palette8e *pal, int N, FILE *fp)
{
int i;

for(i=0;i<N;i++)
{
pal.red = fgetc(fp);
pal.green = fgetc(fp);
pal.blue = fgetc(fp);
}
}

This is hardly difficult code. Also, if for some reason you want to add
alpha to the palette of reverse the channel order, this approach is easilyt
modifiable.


Duh, never thought of that way, thank you very much. And thanks to the
others who answered.
 

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,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top