Make struct member dummy - c

I want to parse a chunk of memory into a struct. The problem is that the members are not one after another and there is some padding.
struct foo {
unsigned int a; // # 0
unsigned int junk; // # 0x4
unsigned int b; // # 0x08
unsigned int more_junk;
.........
};
I don't want to assign each member in the struct for every junk that I have. I know that this is possible with unions but not sure for structs.
Update
I'll make another more clear example:
#include <stdio.h>
#include <string.h>
main()
{
struct w {
unsigned long a;
unsigned long b;
unsigned long c;
unsigned long d;
};
struct w *q;
unsigned long array[] =
{
0x11111111,
0x22222222,
0x33333333,
0x44444444
};
q = (struct w*)array;
printf("%x\n", q->a);
printf("%x\n", q->b);
printf("%x\n", q->c);
printf("%x\n", q->d);
}
The output is:
11111111
22222222
33333333
44444444
Lets say that the 3's are junk. The same example:
#include <stdio.h>
#include <string.h>
main()
{
struct w {
unsigned long a;
unsigned long b;
unsigned long d;
};
struct w *q;
unsigned long array[] =
{
0x11111111,
0x22222222,
0x33333333,
0x44444444
};
q = (struct w*)array;
printf("%x\n", q->a);
printf("%x\n", q->b);
printf("%x\n", q->d);
}
The output is:
11111111
22222222
33333333
But it should be:
11111111
22222222
44444444

there is some padding.
Indeed. This is why structs are unsuitable and dangerous to use for memory mapping purposes.
The problem is that the members are not one after another
I don't want to assign each member in the struct for every junk that I have
Not quite sure what you mean. You don't have to assign anything if you don't want to. You do however need to declare room for where the junk bytes will go. Simply declare a dummy variable in the struct which you later ignore, as you do in the very first struct example.
There is no way around this, the only alternative is to use an entirely different data structure such as a plain byte array of raw data. But that would hardly make your program easier to read.
However, if the junk bytes need not be preserved, i.e you are not doing a memory mapping but just some "cherry picking" of the data you are interested in, then you need no junk bytes in the struct. But you will have to assign every member manually, rather than using memcpy.
I know that this is possible with unions
No it isn't, I think you misunderstand how a union works.

From your question :
Members are not one after another : I suggest you to rearrange the members of your struct so that they are in sync with the memory block you wish to copy.
There is some padding : You can prevent the compiler from padding using __attribute__((__packed__)) keyword when you define your struct, which would direct compiler to stop padding.
struct __attribute__((__packed__)) foo {
unsigned int a; // # 0
unsigned int junk; // # 0x4
unsigned int b; // # 0x08
unsigned int more_junk;
.........
};
After this you can either use memcpy() to copy the contents of the memory block to the struct foo variable or if it is struct foo *ptr then directly point to the memory.
For more info on struct padding and packing refer : Structure padding and packing

Hi friend in GCC you can using this in struct for padding :
Type : Width;
this variable hasn't name;
struct foo {
unsigned int a: 4;
unsigned int: 4; //junk;
unsigned int b: 1;
unsigned int: 7; //more_junk;
};
this struct uses 2 byte of sram memory.
FOR your example:
main() {
struct w {
unsigned long a;
unsigned long b;
unsigned long;
unsigned long d;
};
struct w * q;
unsigned long array[] = {
0x11111111,
0x22222222,
0x33333333,
0x44444444
};
q = (struct w * ) array;
printf("%x\n", q -> a);
printf("%x\n", q -> b);
printf("%x\n", q -> d);
}

Related

I have memory address of an struct store in int variable. Can I dereference the struct using this int value in C?

I have address of an struct store in int variable. Can I dereference the struct??
say: int x = 3432234; // memory address of struct
now I want to access the some struct from it.
I have been suggest these steps.
store the address in an int variable
cast that int to a struct pointer
then dereference it
But don't know how to apply.
If you have a struct foo, the easy way is to not use an int x but make the type a pointer-to-struct foo, struct foo *x. One can use the arrow operator to access members from a valid pointer directly.
#include <stdio.h>
struct foo { int a, b; };
int main(void) {
struct foo foo = { 1, 2 };
struct foo *x = &foo;
printf("%d, %d\n", x->a, x->b);
}
Sometimes, hardware requirements complicate this, but this is the simple solution.
It is very common to use structs this way in mare metal environments as hardware registers are often memory mapped.
typedef struct
{
volatile uint32_t reg1;
const volatile uint32_t reg2;
}PERIPH1__t;
#define PERIPH1ADDRESS 0x56664550UL
/* OR */
uintptr_t PERIPH1ADDRESS = 0x56664550UL;
#define PERIPH1 ((PERIPH1__t *)PERIPH1ADDRESS)
/* somewhere in the code */
PERIPH1 -> reg1 = 34;
uint32_t reg2val = PERIPH1 -> reg2;
if you want to store the address in the integer variable, the best type will be uintptr_t which is guaranteed to accommodate any pointer.
int is signed and on many systems not large enough to store addresses - for example 64 bits systems often have 64 bits addresses and only 32bits integers.

structure after "packed" still bigger than it should be

Problem is solved. Mistake was not to rethink about given datatypes...
The size of following structure is bigger than it should be:
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
struct Y
{
short h;
byte i;
}
#if defined (__GNUC__)
__attribute__((__packed__));
#endif
struct X
{
short a;
byte b;
byte c;
word d;
dword e;
byte f;
byte g;
word h;
short i;
struct Y G[8];
}
#if defined (__GNUC__)
__attribute__((__packed__));
#endif
printf("size of X should be 40 but is %i", sizeof(struct X));
Output:
size of X should be 40 but is 44
I need this structure with a size of 40 Bytes (sum of all elements), 44 is the lowest I can reach. Compiler is GCC C, byte is unsigned char, word is unsigned short and dword is unsigned long. sizeof(Y) is 3. What is the problem here?
The types you define are flawed. Ideally I'd suppose that dword should be double the size of word, but you are defining the two as:
typedef unsigned short word;
typedef unsigned long dword;
And it turns out that on your platform sizeof(unsigned short) is 2, while sizeof(unsigned long) is 8, not 4.
You should really avoid such definitions and use the standard types provided in stdint.h:
byte -> uint8_t
short -> uint16_t
word -> uint16_t
dword -> uint32_t
Finally, your structure declaration is invalid if the macro __GNUC__ is not defined, because you would be missing the final semicolon (;). You can change it to something like this:
#if defined (__GNUC__)
__attribute__((__packed__))
#endif
struct Y
{
uint16_t h;
uint8_t i;
};

How does __attribute__((packed)) for a field affect struct which contains this field?

If I have a field in my struct which is packed, why my whole structure is becoming packed?
Example:
#include <stdio.h>
struct foo {
int a;
} __attribute__((packed));
struct bar {
char b;
struct foo bla;
char a;
};
int main() {
printf("%ld\n", sizeof(struct bar));
return 0;
}
https://ideone.com/bjoZHB
Sizeof of bar struct is 6, but it should be 12, because it should be aligned.
it seems because __attribute__((packed)) means use the minimum memory for structure, it also means that it can ignore alignment for siding members when it is in another structure. Check following structure:
struct bar {
char b;
__attribute__((packed)) int bla;
char a;
};
When you check size for this structure, it will be 6. This happens because it ignores member alignment for 2 side members(a and b here). But this structure:
struct bar {
char b;
__attribute__((packed)) int bla;
char a;
int c;
};
has size of 12, because it is aligned c on 4 bytes boundary. In your case, if you use aligned attribute too at same time, it works as you expect:
struct bar {
char b;
__attribute__((aligned (4), packed)) int bla;
char a;
};
This structure size is 12.
Update:
I only found this in GCC's aligned section of attributes. I think it is related to what I mentioned here:
The aligned attribute can only increase the alignment; but you can
decrease it by specifying packed as well
.Just remember that if you want to keep child structure packed but main structure aligned, you need to use 2 attributes in 2 different declarations. For example following structure has size of 12:
struct foo {
char b;
int a;
} __attribute__((packed));
struct bar {
char b;
__attribute__((aligned(4))) struct foo bla;
char a;
};
but if you use aligned() in declaration of foo as __attribute__((aligned (4), packed)), size will be 16. This happens because foo gets aligned too, and it will not be useful in case of packing.

autoconf: check for offset of a member

I have a structure:
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
char payload[1024];
} bar;
I want to find out, at configure time, if I need to insert padding to make 'payload' double-aligned.
Autoconf provides AC_CHECK_SIZEOF(type) and AC_CHECK_ALIGNOF(type), but what I really need is something like AC_CHECK_OFFSETOF(type, member). If the reported offset was not double-aligned, I could introduce enough padding to make it so.
I could run a little test program that reported offsetof(struct bar, payload), but I don't want to introduce a run-time check into my build system (we cross-compile not infrequently).
Using a zero length bitfield might solve this problem without autotool tricks.
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
int64_t : 0; // or long long whatever integer type is sizeof(double)
char payload[1024];
} bar;
You can use AC_COMPUTE_INT:
AC_COMPUTE_INT([payload_offset], [offsetof(struct bar, payload)], ...)
But it would probably be easier just to use an anonymous union to force alignment:
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
union {
char payload[1024];
double dummy; /* for alignment */
};
} bar;
If you don't want to use a union, you can compute the padding in place:
struct foo {
struct header {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
char padding[(alignof(double) - 1) - ((sizeof(struct header)
+ alignof(double) - 1) % alignof(double))];
char payload[1024];
} bar;
I don't really think that autoconf can tell you that, as it is a matter of the compiler who decides to add padding or not. So I would think that the only reasonable way would be to compile a program that checks if offset of the member equals to what you think it should be equal.

Pointer casting problem with struct array member

I've run across this source in a legacy code base and I don't really know why exactly it behaves the way it does.
In the following code, the pData struct member either contains the data or a pointer to the real data in shared memory. The message is sent using IPC (msgsnd() and msgrcv()). Using the pointer casts (that are currently commented out), it fails using GCC 4.4.1 on an ARM target, the member uLen gets modified. When using memcpy() and everything works as expected. I can't really see what is wrong with the pointer casting. What is wrong here?
typedef struct {
long mtype;
unsigned short uRespQueue;
unsigned short uID;
unsigned short uLen;
unsigned char pData[8000];
} message_t;
// changing the pointer in the struct
{
unsigned char *pData = <some_pointer>;
#if 0
*((unsigned int *)pMessage->pData) = (unsigned int)pData;
#else
memcpy(pMessage->pData, &pData, sizeof(unsigned int));
#endif
}
// getting the pointer out
{
#if 0
unsigned char *pData; (unsigned char *)(*((unsigned int *)pMessage->pData));
#else
unsigned char *pData;
memcpy(&pData, pMessage->pData, sizeof(int));
#endif
}
I suspect it's an alignment problem and either GCC or the processor is trying to compensate. The structure is defined as:
typedef struct {
long mtype;
unsigned short uRespQueue;
unsigned short uID;
unsigned short uLen;
unsigned char pData[8000];
} message_t;
Assuming normal alignment restrictions and a 32-bit processor, the offsets of each field are:
mtype 0 (alignment 4)
uRespQueue 4 (alignment 2)
uID 6 (alignment 2)
uLen 8 (alignment 2)
pData 10 (alignment 1)
On all but the most recent versions of the ARM processor, memory access must be aligned on the ARM processor and with the casting:
*((unsigned int *)pMessage->pData) = (unsigned int)pData;
you are attempting to write a 32-bit value on a misaligned address. To correct the alignment, the address appears to have truncated the LSB's of the address to have the proper alignment. Doing so happened to overlap with the uLen field causing the problem.
To be able to handle this correctly, you need to make sure that you write the value to a properly aligned address. Either offset the pointer to align it or make sure pData is aligned to be able to handle 32-bit data. I would redefine the structure to align the pData member for 32-bit access.
typedef struct {
long mtype;
unsigned short uRespQueue;
unsigned short uID;
unsigned short uLen;
union { /* this will add 2-bytes of padding */
unsigned char *pData;
unsigned char rgData[8000];
};
} message_t;
The structure should still occupy the same amount of bytes since it has a 4-byte alignment due to the mtype field.
Then you should be able to access the pointer:
unsigned char *pData = ...;
/* setting the pointer */
pMessage->pData = pData;
/* getting the pointer */
pData = pMessage->pData;
That is a very nasty thing to do (the thing that's compiled out). You're trying basically to hack the code, and instead of using the data copy in the message (in the provided 8000 bytes for it), you try to put a pointer, and pass it through IPC.
The main issue is sharing memory between processes. Who knows what happens to that pointer after you send it? Who knows what happens to the data it points to? That's a very bad habbit to send out a pointer to data that is not under your control (i.e.: not protected/properly shared).
Another thing that might happen, and is probably what you're actually talking about, is the alignment. The array is of char's, the previous member in the struct is short, the compiler might attempt packing them. Recasting char[] to int * means that you take memory area and represent it as something else, without telling the compiler. You're stomping over the uLen by the cast.
memcopy is the proper way to do it.
The point here is the code "int header = (((int)(txUserPtr) - 4))"
Illustration of UserTypes and struct pointer casting is great of help!
typedef union UserTypes
{
SAUser AUser;
BUser BUser;
SCUser CUser;
SDUser DUser;
} UserTypes;
typedef struct AUser
{
int userId;
int dbIndex;
ChannelType ChanType;
} AUser;
typedef struct AUser
{
int userId;
int dbIndex;
ChannelType ChanType;
} AUser;
typedef struct BUser
{
int userId;
int dbIndex;
ChannelType ChanType;
} BUser;
typedef struct CUser
{
int userId;
int dbIndex;
ChannelType ChanType;
} CUser;
typedef struct DUser
{
int userId;
int dbIndex;
ChannelType ChanType;
} DUser;
//this is the function I want to test
void Fun(UserTypes * txUserPtr)
{
int header = (*((int*)(txUserPtr) - 4));
//the problem is here
//how should i set incoming pointer "txUserPtr" so that
//Fun() would skip following lines.
// I don't want to execute error()
if((header & 0xFF000000) != (int)0xAA000000)
{
error("sth error\n");
}
/*the following is the rest */
}

Resources