Order of data member in a structure

G

Guest

When we have a structure in the following form

typedef struct {
int I1;
int I2;
int I3;
int I4;
float F1;
float F2;
float F3;
float F4;
} TMyStru;

and a code segment as follows;

TMyStru D;
D.I1=0; D.I2=1; D.I3=2; D.I4=3;
D.F1=4.0; D.F2=4.0; D.F3=6.0; D.F4=7.0;
unsigned char *Buf = new unsigned char [sizeof(TMyStru)];
memcpy(Buf, &D, sizorf(TMyStru));


Does "Buf" ALWAYS (regardless of a particular C/C++ compiler) contains the
content of "D" in I1,I2,I3,I4,F1,F2,F3,F4 order ?
ie I1 appears infront of I2 ...
 
J

JKop

posted:
When we have a structure in the following form

typedef struct {
int I1;
int I2;
int I3;
int I4;
float F1;
float F2;
float F3;
float F4;
} TMyStru;

and a code segment as follows;

TMyStru D;
D.I1=0; D.I2=1; D.I3=2; D.I4=3;
D.F1=4.0; D.F2=4.0; D.F3=6.0; D.F4=7.0;
unsigned char *Buf = new unsigned char [sizeof(TMyStru)];
memcpy(Buf, &D, sizorf(TMyStru));


Does "Buf" ALWAYS (regardless of a particular C/C++ compiler) contains
the content of "D" in I1,I2,I3,I4,F1,F2,F3,F4 order ?
ie I1 appears infront of I2 ...


Yes it does.

Just so you know, you don't need to use the heap:

unsigned char Buf[sizeof(TMyStru)];


Only thing to be concerned about is padding bits. On some
systems, some types of variables need to be aligned on a 4
byte boundary in memory. So for your structure, you may
have the following in memory:

---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
|padding|
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------

So when you copy or over overwrite the padding bits, you're
accessing memory that isn't yours. For instance, the system
may utilize those bits for some other variable, like so:

TMyStru blah;
char kk[4];

Now the system may stick kk into the vacant spot:

---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
| kk |
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------


I don't know if there's any rules as to where and when you
can expect padding, but I do know that your always safe
with:

unsigned char
char
signed char

and arrays of them.


-JKop
 
J

John Harrison

JKop said:
posted:
When we have a structure in the following form

typedef struct {
int I1;
int I2;
int I3;
int I4;
float F1;
float F2;
float F3;
float F4;
} TMyStru;

and a code segment as follows;

TMyStru D;
D.I1=0; D.I2=1; D.I3=2; D.I4=3;
D.F1=4.0; D.F2=4.0; D.F3=6.0; D.F4=7.0;
unsigned char *Buf = new unsigned char [sizeof(TMyStru)];
memcpy(Buf, &D, sizorf(TMyStru));


Does "Buf" ALWAYS (regardless of a particular C/C++ compiler) contains
the content of "D" in I1,I2,I3,I4,F1,F2,F3,F4 order ?
ie I1 appears infront of I2 ...


Yes it does.

Just so you know, you don't need to use the heap:

unsigned char Buf[sizeof(TMyStru)];


Only thing to be concerned about is padding bits. On some
systems, some types of variables need to be aligned on a 4
byte boundary in memory. So for your structure, you may
have the following in memory:

---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
|padding|
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------

So when you copy or over overwrite the padding bits, you're
accessing memory that isn't yours. For instance, the system
may utilize those bits for some other variable, like so:

TMyStru blah;
char kk[4];

Now the system may stick kk into the vacant spot:

Yikes!! I hope that isn't true. I know about padding but that the first time
anyone has said that the compiler can use that padding for other purposes,
rather than just leaving it unused.

In fact I'm pretty sure it can't be true, because it would mean the memset
would affect an unrelated variable, making memset unusable on POD types
(unless they happen to be char or arrays of char). If that really is true
then the standard is stupider than I thought.

john
 
J

JKop

John Harrison posted:
JKop said:
posted:
When we have a structure in the following form

typedef struct {
int I1;
int I2;
int I3;
int I4;
float F1;
float F2;
float F3;
float F4;
} TMyStru;

and a code segment as follows;

TMyStru D;
D.I1=0; D.I2=1; D.I3=2; D.I4=3;
D.F1=4.0; D.F2=4.0; D.F3=6.0; D.F4=7.0;
unsigned char *Buf = new unsigned char [sizeof (TMyStru)];
memcpy(Buf, &D, sizorf(TMyStru));


Does "Buf" ALWAYS (regardless of a particular C/C++ compiler)
contains the content of "D" in I1,I2,I3,I4,F1,F2,F3,F4 order ?
ie I1 appears infront of I2 ...


Yes it does.

Just so you know, you don't need to use the heap:

unsigned char Buf[sizeof(TMyStru)];


Only thing to be concerned about is padding bits. On some
systems, some types of variables need to be aligned on a 4
byte boundary in memory. So for your structure, you may
have the following in memory:

---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
|padding|
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------

So when you copy or over overwrite the padding bits, you're
accessing memory that isn't yours. For instance, the system
may utilize those bits for some other variable, like so:

TMyStru blah;
char kk[4];

Now the system may stick kk into the vacant spot:

Yikes!! I hope that isn't true. I know about padding but that the first
time anyone has said that the compiler can use that padding for other
purposes, rather than just leaving it unused.

In fact I'm pretty sure it can't be true, because it would mean the
memset would affect an unrelated variable, making memset unusable on
POD types (unless they happen to be char or arrays of char). If that
really is true then the standard is stupider than I thought.

john


What I'm getting it is that there's nothing in the Standard
that says that that *can't* be done, and for example in the
following:

struct Cow
{
int a;
char b;
int c;
};

I think it would be perfectly reasonable to actually make
use of the vacant space between b and c, which is probably
2 bytes, and so:

int main()
{
Cow blah;

char jack[2];
}

---------
| a |
---------
---------
| b |
---------
---------
|jack[2]|
---------
---------
| c |
---------


C++ contains unions, so why wouldn't it do the above?


-JKop
 
J

John Harrison

What I'm getting it is that there's nothing in the Standard
that says that that *can't* be done, and for example in the
following:

struct Cow
{
int a;
char b;
int c;
};

I think it would be perfectly reasonable to actually make
use of the vacant space between b and c, which is probably
2 bytes, and so:

int main()
{
Cow blah;

char jack[2];
}

---------
| a |
---------
---------
| b |
---------
---------
|jack[2]|
---------
---------
| c |
---------


C++ contains unions, so why wouldn't it do the above?


-JKop

I don't know what the standard says, but I think any compiler manufacturer
that actually did that would have trouble selling their compilers.

Are you confident that the standard allows this?

john
 
J

JKop

John Harrison posted:
I don't know what the standard says, but I think any compiler
manufacturer that actually did that would have trouble selling their
compilers.

Well, from experience working with with MSWindows, they
always use the likes of:

SOMESTUPIDSTRUCTURE blah;
memset(&blah,0,sizeof(blah));


But we're not talking about a competent company here, so
that's a moot point.

Are you confident that the standard allows this?


Confident? I'm neither confident nor unconfident about it,
I'm just proposing the possibility. I'm not about to read
every page of the Standard, although I suppose I could
search for "padding".


-JKop
 
R

Richard Herring

John Harrison said:
[...]
So when you copy or over overwrite the padding bits, you're
accessing memory that isn't yours. For instance, the system
may utilize those bits for some other variable, like so:

TMyStru blah;
char kk[4];

Now the system may stick kk into the vacant spot:
[...]

Yikes!! I hope that isn't true. I know about padding but that the first time
anyone has said that the compiler can use that padding for other purposes,
rather than just leaving it unused.

In fact I'm pretty sure it can't be true, because it would mean the memset
would affect an unrelated variable, making memset unusable on POD types
(unless they happen to be char or arrays of char). If that really is true
then the standard is stupider than I thought.

Don't worry about it. JKop refuses to buy a copy of the standard, so
what he has to say on the subject is mostly worthless FUD.
 
R

Richard Herring

JKop <[email protected]> said:
Richard Herring posted:


FUD.

Actually,

http://www.lrde.epita.fr/~burrus_n/tmp/

But, elsewhere:
I'm not about to read every page of the Standard, although I suppose I
could search for "padding".

It's no use unless you read it.
Where in the C++ Standard does it say that the opinion of
Richard Herring is not "mostly worthless FUD"?
Same place it says yours isn't. In this newsgroup, facts are preferred
over ill-informed opinion. Ill-informed speculation disguised as facts
is even worse.
 
N

Nikolaos D. Bougalis

JKop said:
John Harrison posted:



selling their



Well, from experience working with with MSWindows, they
always use the likes of:

SOMESTUPIDSTRUCTURE blah;
memset(&blah,0,sizeof(blah));

And this has exactly what to do with padding and whether a compiler
uses intra-variable pad as temporary storage?

-n
 
J

JKop

Nikolaos D. Bougalis posted:
And this has exactly what to do with padding and whether a compiler
uses intra-variable pad as temporary storage?

-n


Really now, if I were you I'd feel cheated - how come everyone else gets a
fully functional brain while I get this piece of crap.

I never mentioned "intra-variable" nor "temporary storage".

Long story short, the padding bits aren't yours, but ofcourse you can always
use them anyway, just like you can:

int* k;

*k = 4;


Using memset as in my Microsoft example above in not portable code, as it
contains Undefined Behaviour.

On a PC with an Intel Pentium family CPU, running a Microsft Windows family
operating system, then you *may* have ownership of the padding bits, so
there *may* be nothing wrong with my aformentioned example.

But then this isn't a Microsoft newsgroup.


-JKop
 
N

Nikolaos D. Bougalis

JKop said:
Nikolaos D. Bougalis posted:





Really now, if I were you I'd feel cheated - how come everyone else gets a
fully functional brain while I get this piece of crap.

Resorting to ad-hominems a bit early aren't you?
I never mentioned "intra-variable" nor "temporary storage".

This comment was made in a thread dealing specifically with padding
between variables in a structure, in which you said that a compiler may
use the padding to store temporary variables, since "C++ contains unions."

I quote, from your post, [email protected]:
TMyStru blah;
char kk[4];

Now the system may stick kk into the vacant spot:

---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
| int |
---------
---------
| kk |
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------
---------
| float |
---------

Long story short, the padding bits aren't yours, but ofcourse you can always
use them anyway, just like you can:

int* k;

*k = 4;


Using memset as in my Microsoft example above in not portable code, as it
contains Undefined Behaviour.

It does not contain undefined behavior, your baseless assertions to
that end notwithstanding.

Can you provide one citation from the standard that indicates that that
is undefined behavior? Oh, what's that? You don't read the standard?

-n
 
J

JKop

Nikolaos D. Bougalis posted:


This comment was made in a thread dealing specifically with
padding
between variables in a structure, in which you said that a compiler may
use the padding to store temporary variables, since "C++ contains
unions."

Where the hell did I mention that they have to be
temporary? I suppose if I say "sibling" then that
automically means "brother" too.

It does not contain undefined behavior, your baseless assertions
to
that end notwithstanding.

Can you provide one citation from the standard that indicates that
that
is undefined behavior? Oh, what's that? You don't read
the standard?


I found 14 instances of "padding" in the Standard, none of
them gave anything.

A while back, Ioannis Vranos said that messing with padding
bits is Undefined Behaviour. You there? Could you please
elaborate?


-JKop
 
N

Nikolaos D. Bougalis

JKop said:
Nikolaos D. Bougalis posted:





specifically with


a compiler may



Where the hell did I mention that they have to be
temporary? I suppose if I say "sibling" then that
automically means "brother" too.

The example you provided used what appeared to be temporary TMyStru and
a temporary 4-character array. Even if you did not mean them to be
temporary, and instead intended them to be subsumed by another object,
that changes very little.
baseless assertions


indicates that


the standard?


I found 14 instances of "padding" in the Standard, none of
them gave anything.

A while back, Ioannis Vranos said that messing with padding
bits is Undefined Behaviour. You there? Could you please
elaborate?

The standard prescribes certain actions as having "undefined behavior."
In 1.3.12, it also suggests that undefined behavior may occur where the
standard fails to explicitly state the behavior. In that sense, there
may be some gray area here.

Frankly, I can see where using memset() on an instance of a class may
be problematic, as you may end up overwriting v-tables or other critical
"internal plumbing." With that said, however, using memset() for a
plain-old C-style structure is safe, and a common programming idiom.

-n
 
A

Andrey Tarasevich

John said:
...
In fact I'm pretty sure it can't be true, because it would mean the memset
would affect an unrelated variable, making memset unusable on POD types
(unless they happen to be char or arrays of char). If that really is true
then the standard is stupider than I thought.
...

Formally speaking, in general case 'memset' _is_ pretty much unusable on
any type other than one from the 'char' group. However, storing
unrelated variables in padding space of a struct would break the
functionality of 'memcpy', when used to copy data between two object of
the same POD struct type.
 
J

Jack Klein

comp.lang.c++:

[snip]
Only thing to be concerned about is padding bits. On some
systems, some types of variables need to be aligned on a 4
byte boundary in memory. So for your structure, you may
have the following in memory:
[snip]

So when you copy or over overwrite the padding bits, you're
accessing memory that isn't yours. For instance, the system
may utilize those bits for some other variable, like so:

TMyStru blah;
char kk[4];

Now the system may stick kk into the vacant spot:

This is patently absurd. I can't begin to describe just how stupid
this is. Have you ever heard of the old maxim: "Better to remain
silent and be thought a fool than to speak and remove all doubt"?
 
J

Jack Klein

JKop said:
posted:
Just so you know, you don't need to use the heap:

unsigned char Buf[sizeof(TMyStru)];


Only thing to be concerned about is padding bits. On some
systems, some types of variables need to be aligned on a 4
byte boundary in memory. So for your structure, you may
have the following in memory:
[snip]
So when you copy or over overwrite the padding bits, you're
accessing memory that isn't yours. For instance, the system
may utilize those bits for some other variable, like so:

TMyStru blah;
char kk[4];

Now the system may stick kk into the vacant spot:
[snip]

Yikes!! I hope that isn't true. I know about padding but that the first time
anyone has said that the compiler can use that padding for other purposes,
rather than just leaving it unused.

No, of course it is not true. I have long suspected JKop of being an
idiot, and this post removed all doubt.
 

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,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top