|
example to forbiden and start it........
|
|
|
|
|
what to do if I get an error like:
LINK : fatal error LNK1104: cannot open file "mfc42u.lib"
Error executing link.exe.
|
|
|
|
|
You probably didn't include the MFC Unicode libraries when you installed VC. Run the install again and install them.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
|
Hi, everyone!
What is the function of "#pragma pack(1)"? Anyone can give
me a simple explanation? Or introduce some materials on this
subject?
Thanks in advance,
George
|
|
|
|
|
Typically the compiler will align members of data structures to their elemental word size. For an integer this means on a four-byte boundary. For shorts it is two, doubles are eight, and bytes are unaligned - they will immediately follow their predecessor.
Sometimes, alignment issues can not be tolerated. Examples are communication interfaces and binary data storage. You must often precisely define where every byte of data is located in these types of applications. #pragma pack(1) means align on a 1 byte boundary or in effect, allow the data to be unaligned.
The Ten Commandments For C Programmers
|
|
|
|
|
Thanks, Rick buddy!
For example, in the following data structure,
--------
#pragma pack(1)
typedef struct header
{
unsigned indicator:1;
unsigned id:8;
}_header;
#pragma pack()
--------
Suppose indicator will start at address D and I think id will locate
at D + 8 bits for alignment purpose. Am I correct?
regards,
George
|
|
|
|
|
|
todays CPU's are much faster when they read a 4-byte value from a multiple-of four address, 2-byte values from a multiple-of-two adress, etc.
Certain processor architectures don't even allow to read a value from a misaligned address. On on x86/Pentium, e.g. reading a long from address 0x10001, 0x10002, or 0x10003(which is are not multiples of 4) causes two memory reads and extra overhead.
Compilers adds "fill" bytes to structs, classes and array members members so that it's members ae "well aligned" (it assumes that the beginning of the struct is well aligned). The "maximum padding" done is usually controlled by compiler options, like #pragma pack.
#pragma pack(1) indicates to the VC++ compiler that it should align following struct declarations to full byte adresses (i.e. no padding noe *). e.g. for the
struct foo
{
char c;
int count;
}; ´
Usually you would leave the default pakcing of 8, unless:
a) you have to simulate a certain binary structure - like a binary file header
b) you are very tight with memory and don't care about speed (and have a processor architecture that allows misaligned memory access)
c) you want to organize padding yourself
VC offers #pragma pack(push, <value>) to save the current csetting and #pragma pack(pop) to restore the previous setting. This is advised to use everywhere, since alignment mismatch isn't detected by the linker. (Assume above struct is #included once with pad byte, and once without).
When deciding the memory layout of a struct or class, the C++ standard only guarantees that elements go in memory in the source code order, but how much padding is added is up to the compiler.
Not as brief as you expected, but the basic briefing...
*) There's an exceptionm - bitfields
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
Thanks, peterchen buddy!
I have a further question, for packing value 8.
struct foo
{
char c;
int count;
};
as you said, c will start at address "this", following 3 bytes padding
and 4 bytes for allocation of "count". I want to know why the allocation
is not like this? Allocate 1 bytes for c, then padding 7 bytes, then allocate 4 bytes for "count", then allocate 4 bytes padding to meet 8-byte alignment.
I want to know how to calculate the padding result of a specific struct.
regards,
George
|
|
|
|
|
because int /being 4 bytes) needs to be only on an multiple-of-4 address
I'll give you some examples, with the compiler-added pad bytes named __pad :
struct {
char a;
char b;
__pad[2];
int x;
};
struct {
char a;
char b;
__pad[6];
double x;
};
struct {
double x;
char a;
char b;
__pad[6];
};
struct {
int x;
int y;
char a;
char b;
__pad[2];
};
fun, isn't it?
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
Thanks, peterchen buddy!
I have two further questions,
1. Is the padding method compiler implemention specific or C++ standard?
2. I really get puzzled in some of your samples.
For example,
struct
{
int x;
int y;
char a;
char b;
__pad[2];
}
I think it is not correct, because default packing value is 8 bytes, so
I think the after-packing structure is,
struct
{
int x;
int y;
char a;
char b;
__pad[6];
}
Am I correct?
regards,
George
|
|
|
|
|
1) it's "implementation defined". The standard gurantees only that, in above example, y goes after x, a after y, etc.
This is because the compiler is supposed to optimize this for the target platform. (I.e. if you have a target platform with no alignment rules at all, no padding would happen).
But all compilers for the Intel platform support alignment in a similar way, usually through custom compiler options. And compilers for other platforms will likely have something similar.
2)
try it
struct foo {
int x, y; char a, b;
};
struct bar {
double x; char a, b;
};
void main()
{
cout << "sizeof(foo) = " << sizeof(foo) << endl;
cout << "sizeof(bar) = " << sizeof(bar) << endl;
}
the packing is always determined by both the "pack value" and the struct members involved (I guess it gets really tricky when you combine structs
The idea is if you build an array of foo's
foo arr_foo[10]
the "double" at arr_foo[1] should be aligned by a multiple of 8, hence the structure size must be a multiple of 8.
for
bar arr_bar[10]
the "int" at arr_1 should be aligned by a multiple of 4, so the structure size needs to be a multiple of 4.
The pack value only indicates the maximum padding (the max number of pad bytes is packvalue-1)
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
Thanks, peterchen buddy!
Is the result, (suppose padding value is 8)
(to make each member start at a multiple of 8 address)
struct bar
{
char a;
_padding[7];
double x;
char b;
_padding[7];
};
or, (to make the whole struct a multiple of 8 address)
struct bar
{
char a;
double x;
char b;
_padding[6];
};
regards,
George
|
|
|
|
|
both
the individual members should start at well aligned offsets (that's why the between-member padding), and when "chaining" structs (e.g. in an array), the next struct should start well-aligned, too (that's why the end padding)
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
Dear All,
For "printf("%x",aa);", the "%x" only supports int-type value.
If "aa" is a double-type value and I use "(int)aa" for "%x", the compiler will crop it into 4-byte output, which
is incorrect if integer part of "aa" is larger than 4 bytes.
how to completely present it with Hexadecimal format?
Thanks for answer.
|
|
|
|
|
Here is a quick and dirty hack at it. Hopefully, this can handle date of any size. I have done no testing of it but it might work.
char *HexDisplayValue( char *buffer, void *value, size_t bytecount )
{
char *pbuf = buffer;
BYTE *chval = (BYTE *)value;
for( size_t index = 0; index < bytecount; ++index, ++chval )
pbuf += sprintf( pbuf, "%02X", *chval );
return buffer;
}
The Ten Commandments For C Programmers
|
|
|
|
|
Hmmm, I dunno. %X expects a 4-byte unsigned int, but you're passing a single-byte unsigned char. Perhaps you need to cast it:
char *HexDisplayValue( char *buffer, void *value, size_t bytecount )
{
char *pbuf = buffer;
BYTE *chval = (BYTE *)value;
for( size_t index = 0; index < bytecount; ++index, ++chval )
pbuf += sprintf( pbuf, "%02X", (unsigned int)(*chval) );
return buffer;
}
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
sprintf is an varargs function - things <4 byte will be extended to 4 bytes (and floats to double) by the caller.
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
peterchen wrote:
sprintf is an varargs function - things <4 byte will be extended to 4 bytes (and floats to double) by the caller.
Really? I've never read that anywhere.
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
|
Right, thanks
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
|
Are you looking for the internal representation (Rick's post would give you that), or the "mathematically correct" reporesentation?
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
Mathetically correct..
I need the integer part of a "double" data,
though the integer part might not be 4-bit aligned..
|
|
|
|