Casting the first member of a struct (and back)

723 views
Skip to first unread message

stephan beal

unread,
Aug 7, 2013, 2:06:20 AM8/7/13
to
Hi, Gurus,

i'm trying to clarify my understanding of how exactly the casting rules work for the first member of a C struct. For example...

struct Base {
int foo;
...
};

struct Subclass {
Base base;
...
};

(struct typedefs elided)

Subclass sub = { {...}, ... };
Base * b = (Base*)⊂

It is my understanding (please correct me if i'm wrong) that that is completely kosher in C because C guarantees (IIUC) that the offset of the first member in the struct is 0.

What i'm not clear on is if the reverse of that cast is legal:

Subclass * original = (Subclass*)b;

(insofar as the coder knows that the conversion is legal, of course, e.g. by checking a type-id indicator stored in the base type.)

My intuition says, "if the offset is 0, the reverse cast must be just as legal because the address is the same," but i am experienced enough to know that intuition is only a part of the story when it comes to details like this :/. Additionally, i seem to remember reading that C++ does _not_ guaranty that the addresses are the same for such casts.

Can one of you provide me a bit of enlightenment on this topic?

:-?
--
comp.lang.c.moderated - moderation address: cl...@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.

Francis Glassborow

unread,
Aug 7, 2013, 2:51:08 PM8/7/13
to
On 07/08/2013 07:06, stephan beal wrote:
> Hi, Gurus,
>
> i'm trying to clarify my understanding of how exactly the casting rules work for the first member of a C struct. For example...
>
> struct Base {
> int foo;
> ...
> };
>
> struct Subclass {
> Base base;
> ...
> };
>
> (struct typedefs elided)
>
> Subclass sub = { {...}, ... };
> Base * b = (Base*)⊂

In plain terms, take the memory of sub and treat it as a base. Looks
fine to me because of the prohibition of initial padding in any object.
>
> It is my understanding (please correct me if i'm wrong) that that is
> completely kosher in C because C guarantees (IIUC) that the offset of
> the first member in the struct is 0.
>
> What i'm not clear on is if the reverse of that cast is legal:
>
> Subclass * original = (Subclass*)b;

Whiist this should work in the current context, it is dangerous as it
relies on the memory addresses by a b* actually containing a subclass
object. Hence I would expect that to be generally classed as undefined
behaviour.

>
> (insofar as the coder knows that the conversion is legal, of course,
> e.g. by checking a type-id indicator stored in the base type.)

You are confusing 'legal' with 'will work as expected'. The
implementation takes the programmer's word that a cast is valid. That is
the nature of casts in C. They are effectively an unchecked way of
changing the type of an area of memory.
>
> My intuition says, "if the offset is 0, the reverse cast must be just as legal because the address is the same,"
> but i am experienced enough to know that intuition is only a part of the story when it comes
? to details like this :/. Additionally, i seem to remember reading that
C++ does _not_ guaranty
> that the addresses are the same for such casts.
Well C++ makes the same guarantees as C for Plain Old Data types (i.e
structs that conform to the requirements of C) However, the general
rules in C++ have to accommodate inheritance (possibly multiple). As a
result C++ programmers avoid C-style casts because they are blunt tools
in the context of C++.

I guess one of the resident C specialists will quote you chapter and verse.

Francis

James Kuyper

unread,
Aug 7, 2013, 2:51:11 PM8/7/13
to
"A pointer to a structure object, suitably converted, points to its
initial member (or if that member is a bit-field, then to the unit in
which it resides), and vice versa." (6.7.2.1p15)

The "and vice versa" covers the case that you're asking about.

--
James Kuyper

Jasen Betts

unread,
Aug 7, 2013, 2:51:46 PM8/7/13
to
On 2013-08-07, stephan beal <sgb...@googlemail.com> wrote:

> My intuition says, "if the offset is 0, the reverse cast must be
> just as legal because the address is the same," but i am experienced
> enough to know that intuition is only a part of the story when it
> comes to details like this :/. Additionally, i seem to remember
> reading that C++ does _not_ guaranty that the addresses are the same
> for such casts.

it's syntactically correct, but may fail, especially on bad input.

--
⚂⚃ 100% natural

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Keith Thompson

unread,
Sep 2, 2013, 5:07:15 AM9/2/13
to
Francis Glassborow <francis.g...@btinternet.com> writes:
[...]
> You are confusing 'legal' with 'will work as expected'. The
> implementation takes the programmer's word that a cast is valid. That is
> the nature of casts in C. They are effectively an unchecked way of
> changing the type of an area of memory.

Well, pointer casts are. Numeric casts just convert a value of one type
to another in a (usually) well-defined way.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Reply all
Reply to author
Forward
0 new messages