|
From: Mac R. <re...@no...> - 2002-06-11 15:57:14
|
Compilers are allowed to pack structures in memory any way they want. The
only requirements on the compiler are that:
1. sizeof() will report the actual size
2. field access will work
x86 CPUs (386/486/Pentium/II/III/IV/etc and so on) are much more efficient
working with longs than with shorts. More importantly, these processors
(and most others) are *MUCH* more efficient working with longs that are 4
byte aligned in memory (4 byte aligned means the memory address is evenly
divisible by 4 -- or that the bottom two bits of the address are 0, if you
prefer to think that way). If the compiler packed your structure tightly,
the three longs would all end up 2 byte aligned, but not 4 byte aligned,
and accessing them would take over twice as long. Since the compiler does
not know how you intend to use this structure, it adds some padding so that
the long fields will be properly aligned.
The effective struct you end up using actually looks like this (probably):
struct bitmapfileheader
{
short int signature;/*2bytes*/
short int PADDING1;/*2bytes*/
int filesize;/*4bytes*/
int reserved;/*4bytes*/
int dataoffset;/*4bytes*/
};
That explains why you can't just read the structure directly. Using the
stream operators to push structures/classes into streams and pull them back
out is fine, but it requires that the stream operators be used for both
operations. In your case (reading bitmap files), the header was not
written by a stream operator, so you can't read it back out that way.
*************
It is also unwise to attempt raw structure dumping like this because the
structure layout in memory will change between compilers, and can change
even between versions of the same compiler (GCC 2.95 and GCC 3.1 have some
memory layout differences).
*************
The most "object oriented" way of handling this (which is also the
idealogically correct approach when working with stream
insertion/extraction operators), is to write operator<<() and operator>>()
member functions for your structures. Inside those functions, you use the
code you showed below:
>file.read((char*)&bmpf.signature,sizeof(bmpf.signature));
>file.read((char*)&bmpf.filesize,sizeof(bmpf.filesize));
>file.read((char*)&bmpf.reserved,sizeof(bmpf.reserved));
>file.read((char*)&bmpf.dataoffset,sizeof(bmpf.dataoffset);
but modified to make sense inside that member function. Actually, what
would be _even_better_ is the following:
file >> signature;
file >> filesize;
file >> reserved;
file >> dataoffset;
or possibly even (forgive me if this is in error -- I'm not a big stream
user myself...)
file >> signature >> filesize >> reserved >> dataoffset;
Since you are working with built in data types at this level, the stream
extraction operator know how to read them from the stream directly.
Once you have written those member functions, you can then insert or
extract your structure directly into or out of streams. Any decent book on
C++ programming *SHOULD* have samples of operator<<() and operator>>(),
since it is a relatively important functionality, and one of the primary
benefits of the stream system.
If you insist on raw memory dumping, most compilers have a method of
telling the compiler to pack tightly in memory. This is frequently done
with one of the many "#pragma" directives. Someone with more GCC
background will have to supply the actual command, or you can get it from
the man pages. Using these directives is inherently unportable and will
limit your code to only functioning on GCC on the particular CPU
architecture you are using, so I would recommend using the more object
oriented approach from above.
Good luck,
Mac
At 01:55 PM 6/11/02 -0000, balamurali muraleedharan wrote:
>Sir,
>I know that when u open an image file in the text mode we cant see
>the image but when we open it in binary mode we should be able to
>read the data from it and store it in any structure.Since this is
>what my doubt is all about I present it here.
>
>struct bitmapfileheader
>{
>short int signature;/*2bytes*/
>int filesize;/*4bytes*/
>int reserved;/*4bytes*/
>int dataoffset;/*4bytes*/
>};
>
>int main()
>{
>bitmapfileheader bmpf;
>cout<<sizeof(bmpf);
>}
>here the result shows the size as 16bytes instead of 14bytes
>also while reading into this structure using file.open and
>file.read statement always wrong data is contained in the
>structure where the read data is stored.Why is this so?
>There is error only while reading into the structure as a whole as
>in the case
>file.open("file.bmp",ios::binary|ios::in);
>file.read((char*)&bmpf,sizeof(bmpf));
>This always reads erroneous values into the corresponding elements
>in the structure.But
>file.open("file.bmp",ios::binary|ios::in);
>file.read((char*)&bmpf.signature,sizeof(bmpf.signature));
>file.read((char*)&bmpf.filesize,sizeof(bmpf.filesize));
>file.read((char*)&bmpf.reserved,sizeof(bmpf.reserved));
>file.read((char*)&bmpf.dataoffset,sizeof(bmpf.dataoffset);
>this reads the correct values into the respective elements of the
>structure.
>why is this so?
>why cant we simply read the contents of the file into the
>structure using the first statement?what really happens during
>this process?
>I am using G++ in Linux environment.
>Please help me.
>_________________________________________________________
>Click below to visit monsterindia.com and review jobs in India or
>Abroad
>http://monsterindia.rediff.com/jobs
>
>
>_______________________________________________________________
>
>Don't miss the 2002 Sprint PCS Application Developer's Conference
>August 25-28 in Las Vegas -
http://devcon.sprintpcs.com/adp/index.cfm?source=osdntextlink
>
>_______________________________________________
>Dev-cpp-users mailing list
>Dev...@li...
>https://lists.sourceforge.net/lists/listinfo/dev-cpp-users
>
-
_____________________________ /"\
Mac Reiter \ / ASCII Ribbon Campaign
Nomadics, Inc. X Against HTML Mail
re...@no... / \ (To join the campaign, simply use
this in your signature.)
|