471,571 Members | 1,045 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,571 software developers and data experts.

struct compatibility

Hi,

I'd like to know whether the following code is standard-compliant:
struct generic {
int x;
int a[1];
};
void f(struct generic *s)
{
int i;

for (i = 0; i < 10; i++)
s->a[i] = i;
}
int main(void)
{
struct special {
int x;
int a[10];
} s;

f((struct generic *) &s);

return 0;
}
Thanks,
Christian
Jan 31 '06 #1
6 1806
Le 31-01-2006, Christian Kandeler <ch****************@hob.de> a écrit*:
Hi,

I'd like to know whether the following code is standard-compliant:
struct generic {
int x;
int a[1];
};
void f(struct generic *s)
{
int i;

for (i = 0; i < 10; i++)
s->a[i] = i;
}
int main(void)
{
struct special {
int x;
int a[10];
} s;

f((struct generic *) &s);

return 0;
}


Interesting question...
If s was allocated on the heap, in C99, I think the code
would be standart because of compatibility with flexible
array member.

The standart says that, 6.7.2.1/16-18, if there exist
struct s {
int x;
int a[]; // No size !
};

Then, generic and s are 'compatible' when allocated
with malloc, and also are special and s.
In your example, there is no s, but I do not think
it will create any difference for compilers.
Marc Boyer
Jan 31 '06 #2
Christian Kandeler wrote:
Hi,

I'd like to know whether the following code is standard-compliant:
struct generic {
int x;
int a[1];
};

void f(struct generic *s)
{
int i;

for (i = 0; i < 10; i++)
s->a[i] = i;
}

int main(void)
{
struct special {
int x;
int a[10];
} s;

f((struct generic *) &s);

return 0;
}


No, it is not. Do you want a C99 or C89 answer?
Essentially, offsetof(struct generic, a) needs not
be equal to offsetof(struct special, a)...

BTW:
struct special {
struct generic access_me;
int a[10 - ((sizeof (struct generic) - offsetof(struct generic,
a))/sizeof (int))];
} s;
(with <stddef.h> included) gives you essentially the struct hack,
so you have no "additional badness" related to other struct layout.
The struct hack, even though not covered by the standard, works
presumably on all known implementations.

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Jan 31 '06 #3
Michael Mair wrote:
Christian Kandeler wrote:
I'd like to know whether the following code is standard-compliant:

struct generic {
int x;
int a[1];
};

void f(struct generic *s)
{
int i;

for (i = 0; i < 10; i++)
s->a[i] = i;
}

int main(void)
{
struct special {
int x;
int a[10];
} s;

f((struct generic *) &s);

return 0;
}


No, it is not. Do you want a C99 or C89 answer?
Essentially, offsetof(struct generic, a) needs not
be equal to offsetof(struct special, a)...


Okay. But if I use a flexible array:

struct generic {
int x;
int a[];
}

is the offset the same, then? I'm not sure if I can deduce that from the
standard. If it is, does that make the rest of the code legal?
Christian
Feb 1 '06 #4
In article <44************@individual.net>,
Christian Kandeler <ch****************@hob.de> wrote:
Michael Mair wrote:
Christian Kandeler wrote:
I'd like to know whether the following code is standard-compliant:

struct generic {
int x;
int a[1];
};

void f(struct generic *s)
{
int i;

for (i = 0; i < 10; i++)
s->a[i] = i;
}

int main(void)
{
struct special {
int x;
int a[10];
} s;

f((struct generic *) &s);

return 0;
}


No, it is not. Do you want a C99 or C89 answer?
Essentially, offsetof(struct generic, a) needs not
be equal to offsetof(struct special, a)...


Okay. But if I use a flexible array:

struct generic {
int x;
int a[];
}

is the offset the same, then? I'm not sure if I can deduce that from the
standard. If it is, does that make the rest of the code legal?


With a flexible array, the offset if a is the same as the offset in
_some_ variant of the struct with fixed array size. Lets say the
compiler chooses one offset when the array size is < 10 and another one
if array size is >= 10, and no other offset, then the offset in the
flexible struct is one of those two offsets. But you don't know which
one.

The other difference is that with any fixed size array, the compiler can
assume that the index is within the bounds. If you use a fixed size
array of size 1, then the compiler can legally ignore the index you pass
and always access array element 0, because that is the only one that you
could access legally. With the flexible size array, the compiler must
produce code that works no matter how large the array is. So here you
have an improvement.
Feb 1 '06 #5
Le 01-02-2006, Christian Kandeler <ch****************@hob.de> a écrit*:
Michael Mair wrote:
Christian Kandeler wrote:
I'd like to know whether the following code is standard-compliant:

struct generic {
int x;
int a[1];
};

void f(struct generic *s)
{
int i;

for (i = 0; i < 10; i++)
s->a[i] = i;
}

int main(void)
{
struct special {
int x;
int a[10];
} s;

f((struct generic *) &s);

return 0;
}


No, it is not. Do you want a C99 or C89 answer?
Essentially, offsetof(struct generic, a) needs not
be equal to offsetof(struct special, a)...


Okay. But if I use a flexible array:

struct generic {
int x;
int a[];
}

is the offset the same, then? I'm not sure if I can deduce that from the
standard. If it is, does that make the rest of the code legal?


No. There was a restriction I had not seen at first glance 6.7.2.1/17.
"Assuming that all array membres are aligned the same".

You should malloc s or add some code like
assert( offsetof(generic, a) == offsetof(special, a) ).
Marc Boyer
Feb 1 '06 #6
On Tue, 31 Jan 2006 10:29:43 +0100, Christian Kandeler
<ch****************@hob.de> wrote:
Hi,

I'd like to know whether the following code is standard-compliant:
struct generic {
int x;
int a[1];
};
void f(struct generic *s)
{
int i;

for (i = 0; i < 10; i++)
s->a[i] = i;
}
int main(void)
{
struct special {
int x;
int a[10];
} s;

f((struct generic *) &s);
The standard guarantees that all pointers to struct have the same
representation. Therefore, casting the value of &s will produce a
representable result. It probably won't even change the
representation.

However, there is no guarantee that a struct special and a struct
generic have the same alignment. If a struct generic has a more
restrictive alignment that the struct special s does not meet, any
attempt to dereference the address, as is done in function f, results
in undefined behavior.

Furthermore, the compiler is allowed to insert different quantities of
padding between i and a in the two different structure types. It is
therefore possible that function f is storing its values in padding of
struct special s (if a struct special has the extra padding) or beyond
the end of struct special s (if a struct generic has the extra
padding). I'm not sure about the first but the second definitely
invokes undefined behavior.

Since it is possible for a compliant compiler to produce this
undefined behavior, the answer has to be the code is not compliant.

return 0;
}

Feb 5 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Cgacc20 | last post: by
21 posts views Thread by Kilana | last post: by
7 posts views Thread by Razvan | last post: by
13 posts views Thread by Vincezo Ciaschini | last post: by
5 posts views Thread by Martin Vorbrodt | last post: by
4 posts views Thread by Martin Vorbrodt | last post: by
67 posts views Thread by S.Tobias | last post: by
5 posts views Thread by spasmous | last post: by
2 posts views Thread by Laurent Deniau | last post: by
reply views Thread by XIAOLAOHU | last post: by
reply views Thread by leo001 | last post: by
reply views Thread by lumer26 | last post: by
reply views Thread by lumer26 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.