Reputation: 388
#define MCARD_CLS_TYPE_HD 1
#define MCARD_SN_LEN 13
typedef struct mcard_ipc_list
{
struct mcard_node *owner;
struct
{
struct mcard_ipc_list *next;
struct mcard_ipc_list *prev;
} node;
char sn_buf[MCARD_SN_LEN]; //13 byte
struct len_str sn; //8 byte
struct mcard_smss smss[MCARD_CLS_TYPE_MIN + 1]; //16*3 byte
} _mcard_ipc_list;
struct mcard_smss *smss = NULL;
struct mcard_node *mnode = NULL;
...
smss = mnode->ipc_head.list->smss + MCARD_CLS_TYPE_HD;
the issue is that the data in smss
is not correct in MFC application but ok in win32 console application!
I saw the the address of variables in the watch windows in VS2010.
the result of the win32 console application:
smss 0x0068af61
&mnode->ipc_head.list->smss[1] 0x0068af61
&mnode->ipc_head.list->smss[0] 0x0068af51
mnode->ipc_head.list->sn_buf 0x005aaf3c
the result of the MFC application:
smss 0x00b1ad54
&mnode->ipc_head.list->smss[1] 0x00b1ad51
&mnode->ipc_head.list->smss[0] 0x00b1ad41
mnode->ipc_head.list->sn_buf 0x00b1ad2c
For MFC application, it's obvious that smss
wa not equal to &mnode->ipc_head.list->smss[1]
but has the offset 0x3
!
And we see that mnode->ipc_head.list->sn_buf
occupy 13
bytes, not alligned!
i have solved the problem actually, and there is two methods:
(1)
#pragma pack(push, 1)
#pragma pack(pop)
(2)
#define MCARD_SN_LEN 16
However, i still confused about the the difference between win32 console application and MFC application when byte aligment needed!
issue:
the distance between mnode->ipc_head.list->sn_buf
and &mnode->ipc_head.list->smss[0]
is 21
bytes
both in win32 console application and MFC application, not 24
bytes because (13 + 3) + 8
means 24
! But why?
the memory address should be certain afer the variable defined, of course they have been aligned in memory afer the variable defined! And smss = mnode->ipc_head.list->smss + MCARD_CLS_TYPE_HD;
is just a Assignment Statements,
why the result in MFC application is not 0x00b1ad51
but 0x00b1ad54
? And the phenomenon is reproducible!
So, if any one can help me out?
update:
um, i wrote a MFC demo to figure the 2nd issue out.
struct mcard_smss *smss = NULL;
smss = (struct mcard_smss *)0x00b1ad51;
However, the value of smss
i saw in watch windows in vs2010 is not 0x00b1ad54
but 0x00b1ad51
!
Something changed and amazing! I don't know why
Upvotes: 0
Views: 113
Reputation: 84609
Continuing from the comment, since the compiler can set the size of the fields and padding within a struct, you can use offsetof
macro (stddef.h
) to determine the offset of a member within a macro:
size_t offsetof(type, member);
The man page for offsetof
describes its use and provides an example.
The macro offsetof() returns the offset of the field member from the start of the structure type. This macro is useful because the sizes of the fields that compose a structure can vary across implementations, and compilers may insert different numbers of padding bytes between fields. Consequently, an element's offset is not necessarily given by the sum of the sizes of the previous elements. A compiler error will result if member is not aligned to a byte boundary (i.e., it is a bit field).
Glad it helped, let me know if you have any additional questions.
Upvotes: 3