Given two structures of the same size but different type, does C99
guarantee that pointers to them can be casted one to each other, and
that the order of the elements will be kind of respected?
This code illustrates what I mean:
int main(void) {
struct foo { char c[2]; };
struct bar { char c0; char c1; };
struct foo f;
struct bar b, *bp;
f.c[0] = 'a';
bp = (struct bar*) &f; // guaranteed to be valid?
bp->c0 == 'a'; // guaranteed to hold?
}
Do you just access the address and the field offset is always computed
from left to right so that works even with mixed field types?
-- fxn 10 1655
No. The alignment requirements might be different.
Robert
Xavier Noria wrote: Given two structures of the same size but different type, does C99 guarantee that pointers to them can be casted one to each other, and that the order of the elements will be kind of respected?
Xavier Noria wrote: Given two structures of the same size but different type, does C99 guarantee that pointers to them can be casted one to each other,
Yes; in fact, it's guaranteed that all pointers to structs can be cast
to one another, same size or not (that is, same alignment restrictions,
same representation).
and that the order of the elements will be kind of respected?
This code illustrates what I mean:
int main(void) { struct foo { char c[2]; }; struct bar { char c0; char c1; };
struct foo f; struct bar b, *bp;
f.c[0] = 'a'; bp = (struct bar*) &f; // guaranteed to be valid? bp->c0 == 'a'; // guaranteed to hold? }
Yes, you do have those two guarantees AFAIK. But don't extrapolate from
this. f.c[1] is not necessarily the same as bp->c1, because there may
be padding between c0 and c1 in struct bar. Do you just access the address and the field offset is always computed from left to right so that works even with mixed field types?
Struct members are stored in the order that you specify, but there may
be padding bytes between any two elements in the struct, or after the
last element in the struct (but not at the beginning). Use the offsetof
macro to find the offset of a field in a struct.
--
Pull out a splinter to reply.
I checked the standard: you are right and I was wrong. Sorry!
Robert
Peter Ammon wrote: Xavier Noria wrote:
Given two structures of the same size but different type, does C99 guarantee that pointers to them can be casted one to each other,
Yes; in fact, it's guaranteed that all pointers to structs can be cast to one another, same size or not (that is, same alignment restrictions, same representation).
"Xavier Noria" <fx*@hashref.com> wrote in message
news:31**************************@posting.google.c om... Given two structures of the same size but different type, does C99 guarantee that pointers to them can be casted one to each other, and that the order of the elements will be kind of respected?
No. All that is guaranteed is that a pointer to the first field of the
structure can be converted to a pointer to the structure and back.
This code illustrates what I mean:
int main(void) { struct foo { char c[2]; }; struct bar { char c0; char c1; };
struct foo f; struct bar b, *bp;
f.c[0] = 'a'; bp = (struct bar*) &f; // guaranteed to be valid? bp->c0 == 'a'; // guaranteed to hold? }
No. For all the Standard cares, there may be a full script of Romeo and
Juliet between c0 and c1. In most cases, you will get a match there,
but this is not guaranteed.
Do you just access the address and the field offset is always computed from left to right so that works even with mixed field types?
I am not sure what you are asking here. The . or -> operator involves
computing the offset, yes. This is done at compile time. And yes, they
associate from left to right. Is that what you were asking?
Peter
Peter Pichler wrote: "Xavier Noria" <fx*@hashref.com> wrote in message news:31**************************@posting.google.c om... Given two structures of the same size but different type, does C99 guarantee that pointers to them can be casted one to each other, and that the order of the elements will be kind of respected? No. All that is guaranteed is that a pointer to the first field of the structure can be converted to a pointer to the structure and back.
The guarantees cover more than just this much. We know,
for instance, that all struct pointers have the same size,
the same representation, and the same alignment requirement
(6.2.5/25). There's also a special guarantee (6.5.2.3/5) for
distinct struct types with with a "common initial sequence" of
elements, when those struct types appear in a union. This code illustrates what I mean:
int main(void) { struct foo { char c[2]; }; struct bar { char c0; char c1; };
struct foo f; struct bar b, *bp;
f.c[0] = 'a'; bp = (struct bar*) &f; // guaranteed to be valid? bp->c0 == 'a'; // guaranteed to hold? }
No. For all the Standard cares, there may be a full script of Romeo and Juliet between c0 and c1. In most cases, you will get a match there, but this is not guaranteed.
There's no guarantee that offsetof(struct bar, c1) is one.
But there *is* a guarantee that offsetof(struct bar, c0) and
offsetof(struct foo, c) are both zero.
The only thing I can think of that could torpedo the O.P.'s
code is the possibility that `struct foo' and `struct bar' might
have different alignment requirements (note that the 6.2.5/25
guarantee pertains to the struct pointers, not to the pointed-at
structs). For example, a sufficiently perverse implementation
could allow a `struct foo' to begin pretty much anywhere while
requiring each `struct bar' to start on a 32-byte boundary. In
such a case, even though `bp = (struct bar*) &f' is lossless
(in the sense that a subsequent `(struct foo*) bp' would retrieve
the original value), the value of `bp' could be invalid anyhow,
in the sense that it could not actually point to a `struct bar'
object. Given an invalid `bp', the expression `bp->c0' could
fail even though the `c0' element has no alignment requirement
of its own. Or so it seems to me, at any rate.
Summary: The Standard guarantees that certain kinds of type-
punning with struct pointers will work. Practical implementations
actually permit considerably more than the Standard guarantees.
Still, it's not a practice to be used indiscriminately; as in
other things, overindulgence can lead to hangovers.
-- Er*********@sun.com
Peter Ammon <ge******@splintermac.com> wrote in message news:<U0******************@newssvr27.news.prodigy. com>... This code illustrates what I mean:
int main(void) { struct foo { char c[2]; }; struct bar { char c0; char c1; };
struct foo f; struct bar b, *bp;
f.c[0] = 'a'; bp = (struct bar*) &f; // guaranteed to be valid? bp->c0 == 'a'; // guaranteed to hold? }
Yes, you do have those two guarantees AFAIK. But don't extrapolate from this. f.c[1] is not necessarily the same as bp->c1, because there may be padding between c0 and c1 in struct bar.
Excellent. Thank you very much for the explanation because I was most
likely going to extrapolate :-).
This doubt comes from reading in books about networking in Unix that
pointers to struct sockaddr and struct sockaddr_in can be casted to
one another. Now I wonder the actual assumptions for this to be true,
I will ask this in some Unix-related newsgroup. Do you just access the address and the field offset is always computed from left to right so that works even with mixed field types?
Struct members are stored in the order that you specify, but there may be padding bytes between any two elements in the struct, or after the last element in the struct (but not at the beginning). Use the offsetof macro to find the offset of a field in a struct.
Just curious, why is that padding permitted? How can those dummy
intermediate bytes be leveraged?
-- fxn
On 18 Feb 2004 16:10:54 -0800, fx*@hashref.com (Xavier Noria) wrote in
comp.lang.c: Peter Ammon <ge******@splintermac.com> wrote in message news:<U0******************@newssvr27.news.prodigy. com>...
This code illustrates what I mean:
int main(void) { struct foo { char c[2]; }; struct bar { char c0; char c1; };
struct foo f; struct bar b, *bp;
f.c[0] = 'a'; bp = (struct bar*) &f; // guaranteed to be valid? bp->c0 == 'a'; // guaranteed to hold? }
Yes, you do have those two guarantees AFAIK. But don't extrapolate from this. f.c[1] is not necessarily the same as bp->c1, because there may be padding between c0 and c1 in struct bar.
Excellent. Thank you very much for the explanation because I was most likely going to extrapolate :-).
This doubt comes from reading in books about networking in Unix that pointers to struct sockaddr and struct sockaddr_in can be casted to one another. Now I wonder the actual assumptions for this to be true, I will ask this in some Unix-related newsgroup.
Do you just access the address and the field offset is always computed from left to right so that works even with mixed field types?
Struct members are stored in the order that you specify, but there may be padding bytes between any two elements in the struct, or after the last element in the struct (but not at the beginning). Use the offsetof macro to find the offset of a field in a struct.
Just curious, why is that padding permitted? How can those dummy intermediate bytes be leveraged?
-- fxn
Some processors are either only able to access data objects of certain
sizes when they are located with certain address alignments, or can
access misaligned data but are less efficient, that it takes more time
or more bus cycles.
An ARM processor can only access 32-bit objects (e.g., int or long) at
addresses evenly divisible by 4. Attempting to access such a value at
an incorrectly aligned address will generate a hardware trap.
A Pentium processor can access 32-bit objects at any address, but most
efficiently at addresses evenly divisible by 4. If such a value is
accessed at any other alignment, it takes longer to read or write it.
If the misaligned address causes the bytes of the object to cross
between two cache lines, the access can take vastly longer.
So if you have a struct:
struct my_struct { char x; long y };
....most compilers for 32-bit processors start the struct on an address
evenly divisible by 4 (or perhaps 8), and leave three padding bytes
after x so that y is also located at an address evenly divisible by 4.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Eric Sosman <Er*********@sun.com> wrote in message news:<40***************@sun.com>... structs). For example, a sufficiently perverse implementation could allow a `struct foo' to begin pretty much anywhere while requiring each `struct bar' to start on a 32-byte boundary. In such a case, even though `bp = (struct bar*) &f' is lossless (in the sense that a subsequent `(struct foo*) bp' would retrieve the original value), the value of `bp' could be invalid anyhow, in the sense that it could not actually point to a `struct bar' object. Given an invalid `bp', the expression `bp->c0' could fail even though the `c0' element has no alignment requirement of its own. Or so it seems to me, at any rate.
Wow, now I don't see why the cast is permitted at all.
If I understand your answers correctly, for a pointer to `struct foo'
looks like either people store a true `struct foo*' or either there's
no portable way to get to its fields, even the first one (someone said
it is OK for the first one, but I don't know how to reconcile that
with the fact that bp could be actually invalid)!
What's the point then? How can you use a casted pointer portabily? fx*@hashref.com (Xavier Noria) wrote: Eric Sosman <Er*********@sun.com> wrote in message news:<40***************@sun.com>...
structs). For example, a sufficiently perverse implementation could allow a `struct foo' to begin pretty much anywhere while requiring each `struct bar' to start on a 32-byte boundary. In such a case, even though `bp = (struct bar*) &f' is lossless (in the sense that a subsequent `(struct foo*) bp' would retrieve the original value), the value of `bp' could be invalid anyhow, in the sense that it could not actually point to a `struct bar' object. Given an invalid `bp', the expression `bp->c0' could fail even though the `c0' element has no alignment requirement of its own. Or so it seems to me, at any rate.
Wow, now I don't see why the cast is permitted at all.
The cast is permitted because explicit conversions between different
struct types is useful in other circumstances (e.g., where the structs
have a common initial member), and while I can't read the Committee's
minds, they probably considered that allowing the useful kinds but
disallowing this one would make the definition of casts and/or structs
needlessly complicated.
Richard
Xavier Noria wrote: Eric Sosman <Er*********@sun.com> wrote:
structs). For example, a sufficiently perverse implementation could allow a `struct foo' to begin pretty much anywhere while requiring each `struct bar' to start on a 32-byte boundary. In such a case, even though `bp = (struct bar*) &f' is lossless (in the sense that a subsequent `(struct foo*) bp' would retrieve the original value), the value of `bp' could be invalid anyhow, in the sense that it could not actually point to a `struct bar' object. Given an invalid `bp', the expression `bp->c0' could fail even though the `c0' element has no alignment requirement of its own. Or so it seems to me, at any rate.
Wow, now I don't see why the cast is permitted at all.
Strictly speaking, I don't believe it is. However the definitions
allow such an illegal cast to "work" in many circumstances, for
some value of "work".
Pointers can be cast to and from void*, with the proviso that the
from must be the same type as that originally cast to void*, apart
from special things supplied by malloc and friends.
Don't ask me for C & V. Maybe Dan can confirm or deny.
--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address! This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Thomas Paul Diffenbach |
last post by:
Can anyone point me to an open source library of /statically
allocated/ data structures?
I'm writing some code that would benefit from trees, preferably self
balancing, but on an embedded system...
|
by: tweak |
last post by:
I'm struggling with the concept of typecasting when
setting up a TCP client.
Here's a code snip (modified from W. Richard Stevens Unix Programming
book) to demonstrate where I am struggling:
...
|
by: tweak |
last post by:
I'm struggling with the concept of typecasting when
setting up a TCP client.
Here's a code snip (modified from W. Richard Stevens Unix Programming
book) to demonstrate where I am struggling:
...
|
by: hermes_917 |
last post by:
I want to use memcpy to copy the contents of one struct to another
which is a superset of the original struct (the second struct has extra
members at the end). I wrote a small program to test...
|
by: pmclinn |
last post by:
I've noticed that many programmers use classes to store data about such
things like:
Class Customers
.....Phone
....ID
....Address
End Class....
|
by: Martin Joergensen |
last post by:
Hi,
I wanted to try something which I think is a very good
exercise... I read in data from the keyboard and store them in a
structure. There's a pointer called "data_pointer" which I use to...
|
by: Jess |
last post by:
Hello,
I tried to clear a vector "v" using "v.clear()". If "v" contains
those objects that are non-built-in (e.g. string), then "clear()" can
indeed remove all contents. However, if "v"...
|
by: Mr John FO Evans |
last post by:
Am looking at adding structures to an embedded C emulator but am wondering
what the standard is for copying structures(ie structa=structb) which
contain pointers to memory and which are therefore...
|
by: yugidnu |
last post by:
Hi all,
I have the following problem.
I have to access different types of structures getting passed via a
void pointer.
I have the code snippet here.
...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: ryjfgjl |
last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
| |