By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,404 Members | 1,012 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,404 IT Pros & Developers. It's quick & easy.

cast struct question

P: n/a
Hi All,

This question has to do with interface design. Suppose I have an translation
tool. It can translates structs from type "general" to other types and then
does some processing.

Example:

typedef struct
{
int data1;
int data2;
}general;

typedef struct
{
int data3;
}specific_a;

For example, the translation looks like this:

void translate1(general * input)
{
specific_a * new_specific_a = malloc (.....);
new_specific_a->data3 = input->data1 * input->data2;

/* use here new_specific_a for a while */
}

Suppose have another type:
typedef struct
{
int data4;
int data5;
}specific_b;

In this specific case another translation looks like:

void translate2(general * input)
{
specific_b * new_specific_b = malloc(....);
new_specific_b->data4 = input->data1;
new_specific_b->data5 = input->data2;

/* do some processing with new_specific_b */

}

Because other interfaces are fixed I need type "specific_a" in the
"translate1" method and "specific_b" in "translate2".

I see an optimalization here in the translate2 method, namely:
void translate2(general * input)
{
specific_b * new_specific_b = (specific_b *) input;
}

(Note: I use the structures specific_b and specific_a only for reading).

Instead of generating the new message, I want to cast the struct (because in
this specific case the data items match exactly). Is this allowed?? In other
words, returns a call to new_specific_b->data4 return data1 and
new_specific_b->data5 return data2 or are there some compiler issues to take
keep in mind?

Grz Milux

Jun 11 '07 #1
Share this Question
Share on Google+
12 Replies


P: n/a
Milux wrote On 06/11/07 13:01,:
Hi All,

This question has to do with interface design. Suppose I have an translation
tool. It can translates structs from type "general" to other types and then
does some processing.

Example:

typedef struct
{
int data1;
int data2;
}general;

typedef struct
{
int data3;
}specific_a;

For example, the translation looks like this:

void translate1(general * input)
{
specific_a * new_specific_a = malloc (.....);
new_specific_a->data3 = input->data1 * input->data2;

/* use here new_specific_a for a while */
}

Suppose have another type:
typedef struct
{
int data4;
int data5;
}specific_b;

In this specific case another translation looks like:

void translate2(general * input)
{
specific_b * new_specific_b = malloc(....);
new_specific_b->data4 = input->data1;
new_specific_b->data5 = input->data2;

/* do some processing with new_specific_b */

}

Because other interfaces are fixed I need type "specific_a" in the
"translate1" method and "specific_b" in "translate2".

I see an optimalization here in the translate2 method, namely:
void translate2(general * input)
{
specific_b * new_specific_b = (specific_b *) input;
}

(Note: I use the structures specific_b and specific_a only for reading).

Instead of generating the new message, I want to cast the struct (because in
this specific case the data items match exactly). Is this allowed?? In other
words, returns a call to new_specific_b->data4 return data1 and
new_specific_b->data5 return data2 or are there some compiler issues to take
keep in mind?
In some very specific circumstances (which don't
apply here), the language requires the type punning
to work. The way most compilers make it work in those
special circumstances has the side-effect of making it
work even in cases like yours, where strictly speaking
it is not guaranteed. You are stepping outside the
bounds of the language's guarantees, but the chance
that it will cause trouble is small.

... except that the chance of trouble approaches
100% as time goes by. The two struct types are perfect
matches today, but what will happen to them as the
program is maintained, refined, and extended? You are
pinning your hopes on nothing more than a coincidence,
really. Somebody, someday will change one or the other
of the two "identical twin" structs, and all of a sudden
things will stop working.

You may think that you can solve this problem by
putting great big comment blocks on both structs, warning
the programmer who changes one of them that he must make
the same change in the other. Take it from a battle-
scarred veteran: This does *not* work in the long run.
The compiler does not enforce what you say in comments,
and mistakes *will* happen. Besides, the programmers who
read the comments will curse your name: You will have
violated an important principle of safe implementation
that states there should be exactly one authoritative
description of each data type, function, interface, or
other "thing" in the program. One and only one -- because
as soon as there are two, there can be disagreement.

You are erecting a house of cards on a day when the
air is still, even though you know for certain that
hurricanes will eventually come. Build your card house
if you insist -- but I for one will not sell you an
insurance policy on it.

--
Er*********@sun.com
Jun 11 '07 #2

P: n/a
On Jun 11, 6:00 pm, Eric Sosman <Eric.Sos...@sun.comwrote:
Milux wrote On 06/11/07 13:01,:
Instead of generating the new message, I want to cast the struct (because in
this specific case the data items match exactly). Is this allowed?? In other
words, returns a call to new_specific_b->data4 return data1 and
new_specific_b->data5 return data2 or are there some compiler issues to take
keep in mind?

In some very specific circumstances (which don't
apply here), the language requires the type punning
to work. The way most compilers make it work in those
special circumstances has the side-effect of making it
work even in cases like yours, where strictly speaking
it is not guaranteed. You are stepping outside the
bounds of the language's guarantees, but the chance
that it will cause trouble is small.
Why is this not guaranteed behavior? Is a compiler allowed to generate
struct{int,int} with varying memory footprints? If so, can you please
elaborate what freedoms a compiler has in this case?

I had always thought struct guaranteed the order of the elements. Is
this accurate?
... except that the chance of trouble approaches
100% as time goes by. The two struct types are perfect
matches today, but what will happen to them as the
program is maintained, refined, and extended? You are
pinning your hopes on nothing more than a coincidence,
really. Somebody, someday will change one or the other
of the two "identical twin" structs, and all of a sudden
things will stop working.
The OP did not provide sufficient context to make this conclusion.
Many structures never change by their very definition.

Jun 11 '07 #3

P: n/a
Richard Urich wrote On 06/11/07 15:44,:
On Jun 11, 6:00 pm, Eric Sosman <Eric.Sos...@sun.comwrote:
>>Milux wrote On 06/11/07 13:01,:
>>>Instead of generating the new message, I want to cast the struct (because in
this specific case the data items match exactly). Is this allowed?? In other
words, returns a call to new_specific_b->data4 return data1 and
new_specific_b->data5 return data2 or are there some compiler issues to take
keep in mind?

In some very specific circumstances (which don't
apply here), the language requires the type punning
to work. The way most compilers make it work in those
special circumstances has the side-effect of making it
work even in cases like yours, where strictly speaking
it is not guaranteed. You are stepping outside the
bounds of the language's guarantees, but the chance
that it will cause trouble is small.


Why is this not guaranteed behavior? Is a compiler allowed to generate
struct{int,int} with varying memory footprints? If so, can you please
elaborate what freedoms a compiler has in this case?
We hashed this out a couple weeks ago, in a thread
titled "Is this legal? Aesthetically acceptable?". Read
through it, and come back if you still have questions.
I had always thought struct guaranteed the order of the elements. Is
this accurate?
Yes, but it's not enough to ensure that the O.P.'s
code will work.
> ... except that the chance of trouble approaches
100% as time goes by. The two struct types are perfect
matches today, but what will happen to them as the
program is maintained, refined, and extended? You are
pinning your hopes on nothing more than a coincidence,
really. Somebody, someday will change one or the other
of the two "identical twin" structs, and all of a sudden
things will stop working.

The OP did not provide sufficient context to make this conclusion.
Many structures never change by their very definition.
It seems you've never met Major Murphy:

http://en.wikipedia.org/wiki/Edward_A._Murphy%2C_Jr.

Seriously, if two things are supposed to be -- in fact,
required to be -- identical, they should probably be just
one thing. Otherwise, the proper operation of the program
rests on nothing sturdier than a coincidence. Those of us
who *have* made the Major's acquaintance are distrustful
of mere coincidence.

--
Er*********@sun.com
Jun 11 '07 #4

P: n/a
On Jun 11, 8:43 pm, Eric Sosman <Eric.Sos...@sun.comwrote:
Richard Urich wrote On 06/11/07 15:44,:
Why is this not guaranteed behavior? Is a compiler allowed to generate
struct{int,int} with varying memory footprints? If so, can you please
elaborate what freedoms a compiler has in this case?

We hashed this out a couple weeks ago, in a thread
titled "Is this legal? Aesthetically acceptable?". Read
through it, and come back if you still have questions.
Thank you for letting me know about the article. It was worth the
read, but unfortunately I could not figure out how to apply it to this
example.

Since struct{int,int} S1 need not be equivalent to struct{int,int} S2,
which of these assumptions is not valid? Or is there another
assumption I have failed to enumerate below?

- the alignment requirements of a type (int) is constant throughout a
compiler
- a struct will maintain program order for all elements
- a struct will pad after each variable only enough to meet the
alignment for the next variable's type (int)
The OP did not provide sufficient context to make this conclusion.
Many structures never change by their very definition.

It seems you've never met Major Murphy:

http://en.wikipedia.org/wiki/Edward_A._Murphy%2C_Jr.

Seriously, if two things are supposed to be -- in fact,
required to be -- identical, they should probably be just
one thing. Otherwise, the proper operation of the program
rests on nothing sturdier than a coincidence. Those of us
who *have* made the Major's acquaintance are distrustful
of mere coincidence.

--
Eric.Sos...@sun.com
A network-aligned item and a host-aligned item can be identical on a
given architecture, yet I feel the items should still hold
distinction. I have used type-casting of structs in this instance
before (if same alignment, cast; else, byteswap), and apparently this
was non-portable code. Without devolving into a style debate, can you
please explain why these casts can fail for structs?

My sincere gratitude for the help,

Richard Urich

Jun 11 '07 #5

P: n/a
Richard Urich wrote:
Eric Sosman <Eric.Sos...@sun.comwrote:
.... snip ...
>
>... except that the chance of trouble approaches 100% as time
goes by. The two struct types are perfect matches today, but
what will happen to them as the program is maintained, refined,
and extended? You are pinning your hopes on nothing more than a
coincidence, really. Somebody, someday will change one or the
other of the two "identical twin" structs, and all of a sudden
things will stop working.

The OP did not provide sufficient context to make this conclusion.
Many structures never change by their very definition.
Ah, you have a vision of the future, and know how the program will
be modified, maintained, refined, extended in that future. How did
you acquire this very useful ability?

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
<http://kadaitcha.cx/vista/dogsbreakfast/index.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 11 '07 #6

P: n/a
Richard Urich wrote:
[... about type-punning between "identically arranged" structs ...]

A network-aligned item and a host-aligned item can be identical on a
given architecture, yet I feel the items should still hold
distinction. I have used type-casting of structs in this instance
before (if same alignment, cast; else, byteswap), and apparently this
was non-portable code. Without devolving into a style debate, can you
please explain why these casts can fail for structs?
The point is that the distinct items should be treated
as such, and the program should not try to gloss over the
distinction. It may happen that on Machine M the two variants
are in fact identical -- but does that mean that a program
should rely on this coincidence of representation? No, I'd
say, because on Machine N where the variants differ in some
way the program will break. That's a fragile program; I have
a distaste for fragile programs.

The O.P. noticed that two of his structs just happened to
have similar members and in a similar order, and he tried to
achieve an "optimalization" by pretending the two structs were
identical. I advise against this course unless they truly
*are* identical, and the only way I know of to be sure of that
is to arrange that they are in fact the same struct type.

And, as I said at the end of my original response, the O.P.
is at liberty to ignore my advice and to persist in his folly;
it's not my funeral. (Cue the Therac-25 reference -- but that
was, in fairness, a different sort of problem altogether. Still,
it serves as a sobering, or even terrifying reminder that code
has a way of outlasting its original design parameters.)

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 12 '07 #7

P: n/a
CBFalconer wrote:
Richard Urich wrote:
>Eric Sosman <Eric.Sos...@sun.comwrote:
... snip ...
>>... except that the chance of trouble approaches 100% as time
goes by. The two struct types are perfect matches today, but
what will happen to them as the program is maintained, refined,
and extended? You are pinning your hopes on nothing more than a
coincidence, really. Somebody, someday will change one or the
other of the two "identical twin" structs, and all of a sudden
things will stop working.
The OP did not provide sufficient context to make this conclusion.
Many structures never change by their very definition.

Ah, you have a vision of the future, and know how the program will
be modified, maintained, refined, extended in that future. How did
you acquire this very useful ability?
In fairness to the poor, benighted, ignorant sod -- 'scuse
me, to the "aspirant" -- you and I are overstating the likelihood
that maintenance and modification will break anything that isn't
nailed down. I said it approached 100%, and while that may be
true I conveniently didn't say anything about the rate of approach.
It could be that the half-life of bug appearance might be on the
order of a few million years.

... but you and I, Chuck, bitter experience tells us that it's
on the order of a few million milliseconds. "Oh, ay; and you try
and tell the young people of today that, and they won't believe
you!"

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 12 '07 #8

P: n/a
On Jun 12, 1:54 am, Eric Sosman <esos...@acm-dot-org.invalidwrote:
The O.P. noticed that two of his structs just happened to
have similar members and in a similar order, and he tried to
achieve an "optimalization" by pretending the two structs were
identical. I advise against this course unless they truly
*are* identical, and the only way I know of to be sure of that
is to arrange that they are in fact the same struct type.
The OP noticed he had two structs with identically-typed, identically-
ordered members. He asked if, under those specific circumstances, the
C Standard guarantees they are identical.

You have claimed two structs that are identically coded are, in fact,
not identical as far as C is concerned. I am merely asking for some
guidance on where in the rather lengthy standard I might look to find
supporting evidence for this claim.

The draft standard does show 6.7.2.1#16:
EXAMPLE Assuming that all array members are aligned the same, after
the declarations:
struct s { int n; double d[]; };
struct ss { int n; double d[1]; };
the three expressions:
sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)
have the same value. The structure struct s has a flexible array
member d.

This implies to me that it is safe to cast from one identically-coded
struct to another. If there is some part of the standard which
overrides this behavior, please let me know.
Richard Urich

Jun 12 '07 #9

P: n/a
Richard Urich <Ri**********@gmail.comwrites:
On Jun 12, 1:54 am, Eric Sosman <esos...@acm-dot-org.invalidwrote:
> The O.P. noticed that two of his structs just happened to
have similar members and in a similar order, and he tried to
achieve an "optimalization" by pretending the two structs were
identical. I advise against this course unless they truly
*are* identical, and the only way I know of to be sure of that
is to arrange that they are in fact the same struct type.

The OP noticed he had two structs with identically-typed, identically-
ordered members. He asked if, under those specific circumstances, the
C Standard guarantees they are identical.

You have claimed two structs that are identically coded are, in fact,
not identical as far as C is concerned. I am merely asking for some
guidance on where in the rather lengthy standard I might look to find
supporting evidence for this claim.

The draft standard does show 6.7.2.1#16:
EXAMPLE Assuming that all array members are aligned the same, after
the declarations:
struct s { int n; double d[]; };
struct ss { int n; double d[1]; };
the three expressions:
sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)
have the same value. The structure struct s has a flexible array
member d.

This implies to me that it is safe to cast from one identically-coded
struct to another. If there is some part of the standard which
overrides this behavior, please let me know.
The example specifically assumes that all array members are aligned
the same. The standard does not guarantee that.

I don't think you'll find a specific passage in the standard that says
two identically declared structures aren't guaranteed to have the same
layout. The point is that you won't find a passage that says they
*are* guaranteed to have the same layout.

The ordering of structure members is guaranteed, but the amount of
padding is not. The compiler is not reuqired to use only the minimal
padding required for alignment.

See also C99 6.5.2.3p5:

One special guarantee is made in order to simplify the use of
unions: if a union contains several structures that share a common
initial sequence (see below), and if the union object currently
contains one of these structures, it is permitted to inspect the
common initial part of any of them anywhere that a declaration of
the complete type of the union is visible. Two structures share a
_common initial sequence_ if corresponding members have compatible
types (and, for bit-fields, the same widths) for a sequence of one
or more initial members.

This is guaranteed *only* when the structures are members of a union.
If they aren't, all bets are off.

In practice, it's very likely that you can get away with assuming the
same layout for sufficiently similar structure types. But it's safer,
and much clearer, simply to declare a single structure type so you
*know* that it will always have the same layout.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 12 '07 #10

P: n/a
Richard Urich wrote On 06/12/07 12:56,:
On Jun 12, 1:54 am, Eric Sosman <esos...@acm-dot-org.invalidwrote:
> The O.P. noticed that two of his structs just happened to
have similar members and in a similar order, and he tried to
achieve an "optimalization" by pretending the two structs were
identical. I advise against this course unless they truly
*are* identical, and the only way I know of to be sure of that
is to arrange that they are in fact the same struct type.


The OP noticed he had two structs with identically-typed, identically-
ordered members. He asked if, under those specific circumstances, the
C Standard guarantees they are identical.

You have claimed two structs that are identically coded are, in fact,
not identical as far as C is concerned. I am merely asking for some
guidance on where in the rather lengthy standard I might look to find
supporting evidence for this claim.
Sorry; I misunderstood your question. The passage
that says the two types are incompatible is 6.2.7p1,
third sentence. The description of the special case in
which the type-punning *is* safe is 6.5.2.3p5.
The draft standard does show 6.7.2.1#16:
EXAMPLE Assuming that all array members are aligned the same, after
the declarations:
struct s { int n; double d[]; };
struct ss { int n; double d[1]; };
the three expressions:
sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)
have the same value. The structure struct s has a flexible array
member d.

This implies to me that it is safe to cast from one identically-coded
struct to another. If there is some part of the standard which
overrides this behavior, please let me know.
Note the words "assuming that," which describe a
precondition the language allows but does not require.
Also, examples aren't normative.

--
Er*********@sun.com
Jun 12 '07 #11

P: n/a
On Jun 12, 5:38 pm, Eric Sosman <Eric.Sos...@sun.comwrote:
Sorry; I misunderstood your question. The passage
that says the two types are incompatible is 6.2.7p1,
third sentence. The description of the special case in
which the type-punning *is* safe is 6.5.2.3p5.
Thank you. This is exactly what I was looking for.

Jun 12 '07 #12

P: n/a
Richard Urich wrote:
>
.... snip ...
>
The OP noticed he had two structs with identically-typed, identically-
ordered members. He asked if, under those specific circumstances, the
C Standard guarantees they are identical.

You have claimed two structs that are identically coded are, in fact,
not identical as far as C is concerned. I am merely asking for some
guidance on where in the rather lengthy standard I might look to find
supporting evidence for this claim.
.... snip ...
>
This implies to me that it is safe to cast from one identically-coded
struct to another. If there is some part of the standard which
overrides this behavior, please let me know.
Why bother? At worst, you need a typedef for the common object
type, and then declare two objects of that type. No casts (which
are probably errors) needed.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
<http://kadaitcha.cx/vista/dogsbreakfast/index.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 12 '07 #13

This discussion thread is closed

Replies have been disabled for this discussion.