C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Problem with structs and mem. allocation

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++)
View previous topic :: View next topic  
Author Message
Nafai
Guest





PostPosted: Wed Sep 29, 2004 11:56 am    Post subject: Problem with structs and mem. allocation Reply with quote



Hi. Have a look at this program:

struct tmp {
short a;
int b;
short c;
};

int main()
{
ofstream f("tmp.bin",ios::binary);
tmp t; t.a=5; t.b=2000; t.c=2;

f.write((const char*)&t.a,sizeof(short));
f.write((const char*)&t.b,sizeof(int));
f.write((const char*)&t.c,sizeof(char));
f.close();

ifstream g("tmp.bin", ios::binary);
tmp s;

g.read((char*)&s,sizeof(tmp));

cout << s.a << " " << s.b << " " << s.c << " " << endl;
cout << &s.a << " " << &s.b << " " << &s.c << " " << endl;
g.close();
}

The output should be (supposing &s==0x22fd48):

5 2000 2
0x22fd48 0x22fd4a 0x22fd4e

But the actual output is:

5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50

So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it starts
after 4 bytes. That's why the g.read(...) doesn't work.

I tried:

but: cout << *((int*)((char*) (&s)+sizeof(short)))

and it output 2000.

In conclusion: &s+sizeof(s.a) != &s.b

Is all this my mistake or am I right??? I'm looking forward to an
explanation.

Thanks!






Back to top
John Harrison
Guest





PostPosted: Wed Sep 29, 2004 12:11 pm    Post subject: Re: Problem with structs and mem. allocation Reply with quote




"Nafai" <nafai3000 (AT) yahoo (DOT) es> wrote

Quote:
Hi. Have a look at this program:

struct tmp {
short a;
int b;
short c;
};

int main()
{
ofstream f("tmp.bin",ios::binary);
tmp t; t.a=5; t.b=2000; t.c=2;

f.write((const char*)&t.a,sizeof(short));
f.write((const char*)&t.b,sizeof(int));
f.write((const char*)&t.c,sizeof(char));
f.close();

ifstream g("tmp.bin", ios::binary);
tmp s;

g.read((char*)&s,sizeof(tmp));

cout << s.a << " " << s.b << " " << s.c << " " << endl;
cout << &s.a << " " << &s.b << " " << &s.c << " " << endl;
g.close();
}

The output should be (supposing &s==0x22fd48):

5 2000 2
0x22fd48 0x22fd4a 0x22fd4e

But the actual output is:

5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50

So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it starts
after 4 bytes. That's why the g.read(...) doesn't work.

Right. Now what made you think that they had to be contiguous in memory?

Quote:

I tried:

but: cout << *((int*)((char*) (&s)+sizeof(short)))

and it output 2000.

In conclusion: &s+sizeof(s.a) != &s.b

Is all this my mistake or am I right??? I'm looking forward to an
explanation.


Compilers are allowed to add 'padding' between the data members of a struct
or class. They do this for efficiency reasons. Most compilers will have
compiler specific options to alter the padding or to turn it off entirely.

Alternatively you could read your data in the same way that you wrote it,
that would be the sensible thing to do.

john



Back to top
Nafai
Guest





PostPosted: Wed Sep 29, 2004 12:34 pm    Post subject: Re: Problem with structs and mem. allocation Reply with quote



Quote:

But the actual output is:

5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50

So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it
starts
after 4 bytes. That's why the g.read(...) doesn't work.

Right. Now what made you think that they had to be contiguous in memory?


I have seen most times things like g.read((char*)&s,sizeof(tmp)); to read a
full struct with one instruction.



Back to top
John Harrison
Guest





PostPosted: Wed Sep 29, 2004 1:11 pm    Post subject: Re: Problem with structs and mem. allocation Reply with quote


"Nafai" <nafai3000 (AT) yahoo (DOT) es> wrote

Quote:

But the actual output is:

5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50

So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it
starts
after 4 bytes. That's why the g.read(...) doesn't work.

Right. Now what made you think that they had to be contiguous in memory?


I have seen most times things like g.read((char*)&s,sizeof(tmp)); to read
a
full struct with one instruction.


That code is OK providing that you read and write in the same way. Your
mistake was reading one way and writing another. Providing you don't mind
any padding bytes being written out to the file, you can read and write a
whole struct in one go.

And of course any binary read or write is not portable across machines,
compilers, etc. etc.

john



Back to top
Karl Heinz Buchegger
Guest





PostPosted: Wed Sep 29, 2004 1:35 pm    Post subject: Re: Problem with structs and mem. allocation Reply with quote

Nafai wrote:
Quote:


But the actual output is:

5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50

So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it
starts
after 4 bytes. That's why the g.read(...) doesn't work.

Right. Now what made you think that they had to be contiguous in memory?


I have seen most times things like g.read((char*)&s,sizeof(tmp)); to read a
full struct with one instruction.

Right. Now search the same program and you will find that those programs
also write a struct in one rush

g.write( char*)&s, sizeof(tmp) );

and *never* by writing each struct member individually.
(Except of course when the programmer was aware of the padding issue
and took it into account. But thats rare).

--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]

Back to top
Nafai
Guest





PostPosted: Wed Sep 29, 2004 6:47 pm    Post subject: Re: Problem with structs and mem. allocation Reply with quote

I came across this problem when reading a BMP file. I defined a struct for
the header and I got into trouble when reading the whole struct. So I have
to read each element of the header (more than 20) one by one? Isn't there
any easier way?


"Karl Heinz Buchegger" <kbuchegg (AT) gascad (DOT) at> escribió en el mensaje
news:415ABA0B.28A162D0 (AT) gascad (DOT) at...
Quote:
Nafai wrote:


But the actual output is:

5 131072 -2764
0x22fd48 0x22fd4c 0x22fd50

So the problem is that the parts of the struct are not continuous in
memory!!! I mean, s.b should start 2 bytes after &s but actually it
starts
after 4 bytes. That's why the g.read(...) doesn't work.

Right. Now what made you think that they had to be contiguous in
memory?


I have seen most times things like g.read((char*)&s,sizeof(tmp)); to read
a
full struct with one instruction.

Right. Now search the same program and you will find that those programs
also write a struct in one rush

g.write( char*)&s, sizeof(tmp) );

and *never* by writing each struct member individually.
(Except of course when the programmer was aware of the padding issue
and took it into account. But thats rare).

--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]



Back to top
Julián Albo
Guest





PostPosted: Wed Sep 29, 2004 6:53 pm    Post subject: Re: Problem with structs and mem. allocation Reply with quote

Nafai wrote:

Quote:
I came across this problem when reading a BMP file. I defined a struct for
the header and I got into trouble when reading the whole struct. So I have
to read each element of the header (more than 20) one by one? Isn't there
any easier way?

Write a file that describes the format of the header, and write a program
that reads this file and generates the code for reading the header.

Of course is more work, but is reusable.

--
Salu2

Back to top
John Harrison
Guest





PostPosted: Wed Sep 29, 2004 9:33 pm    Post subject: Re: Problem with structs and mem. allocation Reply with quote


"Nafai" <nafai3000 (AT) yahoo (DOT) es> wrote

Quote:
I came across this problem when reading a BMP file. I defined a struct for
the header and I got into trouble when reading the whole struct. So I have
to read each element of the header (more than 20) one by one? Isn't there
any easier way?


Well to be strictly portable you have to read the file one byte at a time,
not just one field at a time. How do you know that the format of an integer
in the BMP file (say) corresponds to the format of an int in your compiler?

If you don't mind not being portable then you should look at compiler
options or pragmas that will allow you to control the padding in your
struct. Then you can read the whole struct in one go.

john



Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.