pointer to flexible array of structures in other structure

U

ulyses

I'm trying to put pointer to flexible array of structures in other
structure. I want to have pointer to array of pixels in screen
structure. Here is mine code, but I think it isn't quite all right:

struct pixel
{
int x;
int y;
int color;
};

struct display
{
pixel *screen;
};

Now I would like to do something like that (to have screen made of 10
pixels):

struct display scr;
scr.screen = (struct pixel*)malloc(10*(sizeof(struct pixel)));
scr.screen[0].x = 10;

and it is working, but what is worrying also
scr.screen[11].x = 10;

or
scr.screen[100].x = 10;

is working. I don't now what is wrong. I'm not sure but I think I'm
making mistake when defining structures. How should I define flexible
array of structures in structure? And how should I point it?

Thanks for help and Merry Xmas,
John
 
K

Kenneth Brody

ulyses said:
I'm trying to put pointer to flexible array of structures in other
structure. I want to have pointer to array of pixels in screen
structure. Here is mine code, but I think it isn't quite all right:

struct pixel
{
int x;
int y;
int color;
};

struct display
{
pixel *screen;
};

Now I would like to do something like that (to have screen made of 10
pixels):

struct display scr;
scr.screen = (struct pixel*)malloc(10*(sizeof(struct pixel)));

1) Don't cast the return from malloc(), as it only hides the error of
forgetting the proper header file.

2) Rather than take sizeof(struct pixel), a "better" solution is to
use "sizeof(*scr.screen)", as this allows scr.screen to change.

scr.screen = malloc(10*sizeof(*scr.screen));

3) Don't forget to check the return for NULL.
scr.screen[0].x = 10;

and it is working, but what is worrying also
scr.screen[11].x = 10;

or
scr.screen[100].x = 10;

is working. I don't now what is wrong. I'm not sure but I think I'm
making mistake when defining structures. How should I define flexible
array of structures in structure? And how should I point it?

What's "wrong" is your expectation that C will do the bounds checking
for you, which it does not. If you need this, then you should store
the number of pixels allocated:

struct display
{
int numpixel;
struct pixel *screen;
};

After allocating scr.screen, set scr.numpixel to the number of pixels
allocated. You then need to do your own bounds checking, perhaps
through a function:

[Note: Risking public humiliation by posting untested code.]

pixel *GetPixel(struct display *pdisp, int subscript)
{
ASSERT(subscript >= 0 && subscript < pdisp->numpixel);
return(&pdisp->screen[subscript]);
}

Now, if you attempt:

GetPixel(&scr,100)->x = 10;

you will get an assertion error.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
U

ulyses

I see. Thanks for your help Kenneth. Still one thing is interesting.
How can scr.screen[100].x = 10 work when the array's size is 10? What
is more I can get the value using scr.screen[100].x, e.g. for printf.

Where is this put in the memory, when only 10 'positions' are alocated?
Is it placed somewhere in memory and for example some other app can
erease it?
 
K

Keith Thompson

ulyses said:
I'm trying to put pointer to flexible array of structures in other
structure. I want to have pointer to array of pixels in screen
structure. Here is mine code, but I think it isn't quite all right:

struct pixel
{
int x;
int y;
int color;
};

struct display
{
pixel *screen;
};

There's a problem here. You've defined a type called "struct pixel";
there is no type called "pixel". This should be

struct pixel *screen;

<OT>
In C++ the type "struct pixel" can be referred to as "pixel", but if
you were programming in C++ you'd have posted to comp.lang.c++,
wouldn't you?
Now I would like to do something like that (to have screen made of 10
pixels):

struct display scr;
scr.screen = (struct pixel*)malloc(10*(sizeof(struct pixel)));
scr.screen[0].x = 10;

and it is working,

So far, so good, except that the cast on the malloc() is unnecessary
and can mask errors such as forgetting to "#include <stdlib.h>" or
compiling your C code with a C++ compiler. If you get an error
message without the cast, you need to fix the error, not hide it
with a cast that says to the compiler, "Shut up, I know what I'm doing".

The recommended style is

str.screen = malloc(10 * *scr.screen);

By not referring to the type "struct pixel" in the malloc() call, you
don't need to change the call if the type of scr.screen changes later
on.
but what is worrying also
scr.screen[11].x = 10;

or
scr.screen[100].x = 10;

is working. I don't now what is wrong. I'm not sure but I think I'm
making mistake when defining structures. How should I define flexible
array of structures in structure? And how should I point it?

No, "scr.screen[11].x = 10;" is not "working". It's clobbering memory
beyond the end of your array, which invokes undefined behavior. That
means anything can happen, including having it appear to "work".

C doesn't allow you to index beyond the end of an array object, but it
doesn't do anything to prevent you from doing so. If you index past
the end of an array anyway, the compiler isn't obliged to do anything
about it. It's entirely your responsibility to stay within the bounds
of your object. This allows better performance when you don't make
mistakes, at the expense of arbitrarily bad behavior when you do make
mistakes.

You should probably have a second member in your "struct display" that
keeps track of how many pixels you've allocated. For example:

struct pixel
{
int x;
int y;
int color;
};

struct display
{
struct pixel *screen;
size_t pixel_count;
};

struct display scr;
scr.screen = malloc(10 * sizeof *scr.screen);
if (scr.screen == NULL) {
scr.pixel_count = 0; /* malloc failed */
}
else {
scr.pixel_count = 10;
}


The allocation and initialization should probably be encapsulated in a
function that takes the number of pixels as an argument. You might
want more elaborate error handling as well.

What you have so far is a decent starting point, but there are a few
things you should think about as you develop it further.

I find the use of the terms "screen" and "display" confusing. They
tend to be nearly synonymous in my mind, but you're not using them
consistently as far as I can tell. "display" is the name of the
structure, "screen" is the name of the member of that structure that
points to the array of pixels, but "scr", an abbreviation of "screen",
is also the name of an object of type 'struct display". Pick a
consistent naming scheme now, before your program becomes too
complicated to go back and fix.

Also, a screen/display is more than a linear array of pixels. You're
going to want to keep track of the horizontal and vertical dimensions,
i.e., you'll need a dynamic 2-dimensional array. Section 6 of the
comp.lang.c FAQ has some good tips on this.
 
K

Keith Thompson

ulyses said:
I see. Thanks for your help Kenneth. Still one thing is interesting.
How can scr.screen[100].x = 10 work when the array's size is 10? What
is more I can get the value using scr.screen[100].x, e.g. for printf.

Please provide context when you post a followup. See
<http://cfaj.freeshell.org/google/> for instructions on how to do this
in spite of Google's broken interface.

Given that scr.screen points to a 10-element array,
scr.screen[100].x= 10
doesn't "work". It probably clobbers memory outside the allocated
bounds of the object, invoking undefined behavior. If it happens that
the clobbered memory is within your program's address space, and isn't
currently being used, it can appear to "work". If you're lucky, the
program will crash when you try to do this. Unfortunately, there are
no guarantees. It's your job to avoid doing this.
 
U

ulyses

Thanks Keith, now everything seems clear. I think that your last post
solves the whole problem. Thanks to Kenneth also.

John
 
D

Dave Thompson

The recommended style is

str.screen = malloc(10 * *scr.screen);
Not quite. (Missing 'sizeof'.)

<snip rest>

- David.Thompson1 at worldnet.att.net
 

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,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top