Discussion:
C Question ...
(too old to reply)
John
2009-08-12 23:09:28 UTC
Permalink
I have the following struct:

typedef struct _MINE
{
UCHAR a[6];
UCHAR B[6];
USHORT C;
USHORT D;
USHORT E;
UCHAR F;
UCHAR G;
USHORT H;
UCHAR I[6];
UINT J;
UCHAR K[6];
UINT L;
} MINE, *PMINE;

When I try to use this in code, I have this ...
PMINE a;
a = (PMINE) someBuffer;

Now, someBuffer has all of the correct stuff filled into it. When I set "a"
to point to it, everything in "a" is fine except the last UINT L. For some
reason, I get this:

a->A == OK;
a->B == OK;
a->C == OK;
a->D == OK;
a->E == OK;
a->F == OK;
a->G == OK;
a->H == OK;
a->I == OK;
a->J == OK;
a->K == OK;
a->L == NOT OK;

a->L = Almost OK. It appears as though a->L is really only 2 bytes instead
of 4 in the debugger. Also, it also appears as though a->L starts pointing
2 bytes after a->K. So, in memory, it looks like this:

a->K 00, 01, 02, 03, 04, 05; FINE
06 07; Two bytes that I need but are skipped
a->L = 08, 09;

Then a bunch of zeros appear after 09. If I set my struct to this:

typedef struct _MINE
{
UCHAR a[6];
UCHAR B[6];
UCHAR C[2];
UCHAR D[2];
UCHAR E[2];
UCHAR F;
UCHAR G;
UCHAR H[2];
UCHAR I[6];
UCHAR J[4];
UCHAR K[6];
UCHAR L[4];
} MINE, *PMINE;

Everything appears to point to the right stuff. However, if I do this then
I have to do some type of memcpy from L into a UINT. I don't want to do
that because it is extrememly ghetto, and this should be working. Can
anybody tell what's wrong? BTW, this is a kernel driver.

Thanks.
Scott McPhillips [MVP]
2009-08-12 23:26:53 UTC
Permalink
It is quite common for the compiler to insert padding (unused bytes) into
struct declarations. If you need to declare a struct with no padding use
#pragma pack, just before and just after the declaration:

#pragma pack(push)
#pragma pack(1) // one byte packing
typedef ....
{ };
#pragma pack(pop) // restore normal packing
Post by John
typedef struct _MINE
{
UCHAR a[6];
UCHAR B[6];
USHORT C;
USHORT D;
USHORT E;
UCHAR F;
UCHAR G;
USHORT H;
UCHAR I[6];
UINT J;
UCHAR K[6];
UINT L;
} MINE, *PMINE;
When I try to use this in code, I have this ...
PMINE a;
a = (PMINE) someBuffer;
Now, someBuffer has all of the correct stuff filled into it. When I set
"a" to point to it, everything in "a" is fine except the last UINT L. For
a->A == OK;
a->B == OK;
a->C == OK;
a->D == OK;
a->E == OK;
a->F == OK;
a->G == OK;
a->H == OK;
a->I == OK;
a->J == OK;
a->K == OK;
a->L == NOT OK;
a->L = Almost OK. It appears as though a->L is really only 2 bytes
instead of 4 in the debugger. Also, it also appears as though a->L starts
a->K 00, 01, 02, 03, 04, 05; FINE
06 07; Two bytes that I need but are skipped
a->L = 08, 09;
typedef struct _MINE
{
UCHAR a[6];
UCHAR B[6];
UCHAR C[2];
UCHAR D[2];
UCHAR E[2];
UCHAR F;
UCHAR G;
UCHAR H[2];
UCHAR I[6];
UCHAR J[4];
UCHAR K[6];
UCHAR L[4];
} MINE, *PMINE;
Everything appears to point to the right stuff. However, if I do this
then I have to do some type of memcpy from L into a UINT. I don't want to
do that because it is extrememly ghetto, and this should be working. Can
anybody tell what's wrong? BTW, this is a kernel driver.
Thanks.
--
Scott McPhillips [VC++ MVP]
John
2009-08-12 23:35:35 UTC
Permalink
I need to stop jumping back and forth from C to C#. Thanks guys, I'll give
it a whirl. I'm sure that's it.
Post by Scott McPhillips [MVP]
It is quite common for the compiler to insert padding (unused bytes) into
struct declarations. If you need to declare a struct with no padding use
#pragma pack(push)
#pragma pack(1) // one byte packing
typedef ....
{ };
#pragma pack(pop) // restore normal packing
Post by John
typedef struct _MINE
{
UCHAR a[6];
UCHAR B[6];
USHORT C;
USHORT D;
USHORT E;
UCHAR F;
UCHAR G;
USHORT H;
UCHAR I[6];
UINT J;
UCHAR K[6];
UINT L;
} MINE, *PMINE;
When I try to use this in code, I have this ...
PMINE a;
a = (PMINE) someBuffer;
Now, someBuffer has all of the correct stuff filled into it. When I set
"a" to point to it, everything in "a" is fine except the last UINT L.
a->A == OK;
a->B == OK;
a->C == OK;
a->D == OK;
a->E == OK;
a->F == OK;
a->G == OK;
a->H == OK;
a->I == OK;
a->J == OK;
a->K == OK;
a->L == NOT OK;
a->L = Almost OK. It appears as though a->L is really only 2 bytes
instead of 4 in the debugger. Also, it also appears as though a->L
a->K 00, 01, 02, 03, 04, 05; FINE
06 07; Two bytes that I need but are skipped
a->L = 08, 09;
typedef struct _MINE
{
UCHAR a[6];
UCHAR B[6];
UCHAR C[2];
UCHAR D[2];
UCHAR E[2];
UCHAR F;
UCHAR G;
UCHAR H[2];
UCHAR I[6];
UCHAR J[4];
UCHAR K[6];
UCHAR L[4];
} MINE, *PMINE;
Everything appears to point to the right stuff. However, if I do this
then I have to do some type of memcpy from L into a UINT. I don't want
to do that because it is extrememly ghetto, and this should be working.
Can anybody tell what's wrong? BTW, this is a kernel driver.
Thanks.
--
Scott McPhillips [VC++ MVP]
Igor Tandetnik
2009-08-12 23:28:40 UTC
Permalink
Post by John
typedef struct _MINE
{
UCHAR a[6];
UCHAR B[6];
USHORT C;
USHORT D;
USHORT E;
UCHAR F;
UCHAR G;
USHORT H;
UCHAR I[6];
UINT J;
UCHAR K[6];
UINT L;
} MINE, *PMINE;
When I try to use this in code, I have this ...
PMINE a;
a = (PMINE) someBuffer;
Now, someBuffer has all of the correct stuff filled into it. When I
set "a" to point to it, everything in "a" is fine except the last
UINT L.
Compiler introduced padding so as to place L at the 4-byte boundary. Try

#pragma pack(push, 1)
typedef struct _MINE
{
...
} MINE, *PMINE;
#pragma pack(pop)

but be aware that accessing MINE.L may crash (generate a hardware fault)
on some non-x86 architectures.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Continue reading on narkive:
Loading...