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.
Related
I have gone through this very good article
https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule
but I didn't understood of aliasing with union, what I know about aliasing is with char/ unsigned char, which is a compiler exception according to this article. so , how I used to do aliasing with char/ unsigned char is like,
// lets say I have struct blah , having int member non_sense, cmmn_sense, intelligence...
struct blah *foo, *foo2;
unsigned char buffer [512];
foo = (struct blah *) (buffer+0);
//now accessing members
foo->non_sense = -1;
foo->non_snese = 0;
foo->intelligence =1;
// now we can use another struct after that ..
foo2 = (struct blah*) (buffer + sizeof(struct blah));
Please correct me if I am wrong some where :)
Q.So how can I do the same with union?
NOTE I didn't encountered with union much, so I don't know its proper use too.
I have also searched for aliasing with enum, but didn't understood much ,
Q.If possible with enum how will we do that?
Sorry for my English, not that good and please openly suggest correction for my misconception or terminology in my question to correct ...
Yes, almost any pointer (including your examples) is unsafe (except if it accessed by char).
Below is safe (access by char pointer):
struct blah x;
char *y = (char *)&x;
for(size_t i = 0; i < sizeof(x); i++)
printf("[%zu] = %hhd\n", i, y[i];
The correct way is to memcpy buffer into the struct or to have char array as one of the union members.
struct a
{
int a;
short b;
char x[2];
double z[3];
};
union b
{
unsigned char buffer[512];
struct a sa[512/32];
};
double foo(char *x)
{
struct a c;
memcpy(&c, x, sizeof(c));
return c.z[0];
}
double bar(void)
{
union b c;
read_from_uart(&c, 512);
return c.sa[5].z[1];
}
Q.If possible with enum how will we do that?
Enum is an integer. Same rules as for integers.
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.
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);
}
I have 2 headers that need to define 2 similar structures. One structure should be aligned to 32bytes and other is similar but doesn't need to align to 32bytes so I can save some memory here. One is included in the other. Here is main_header.h
struct mainStruct
{
int a;
int b;
int c;
char pad[20];
};
Following is sub_header.h
#include "main_header.h"
struct subStruct
{
int a;
int b;
int c;
};
Now what I wish to do is define subStruct in a way that, whenever i change mainStruct other than pad[20] all other fields should be updated in subStruct. That is, if tomorrow, I make mainStruct like this:
struct mainStruct
{
int a;
int b;
int c;
int d;
char pad[16];
};
then, automatically it should be reflected in sub_header.h as
struct subStruct
{
int a;
int b;
int c;
int d;
};
Is there an efficient way of doing it using some kind of Macros or other preprocessor directives??
And subStruct should always be derived from mainStruct and not other way around, this is very important.
Thanks in advance.
Did you consider the other way around; including subStruct as an element in mainStruct? Like this:
struct sub {
int a, b, c;
};
struct main {
struct sub head;
char dummy[16];
};
True, it does take an extra layer of syntax to get at a, b or c, but the memory layout and performance should be the same.
Otherwise, there's nothing preventing you from using a macro, as you suggest yourself:
#define SUB_FIELDS int a; int b; int c;
struct main {
SUB_FIELDS
char dummy[16];
};
struct sub {
SUB_FIELDS
};
Well, that's why C++ was initially invented. But if you wish to stay with plain C (there could be reasons for such decision) you may check GLib / GObject type system implemented as a set of macros over plain C.
I have a union as follows:
typedef unsigned long GT_U32;
typedef unsigned short GT_U16;
typedef unsigned char GT_U8;
typedef union
{
GT_U8 c[8];
GT_U16 s[4];
GT_U32 l[2];
} GT_U64;
I want to cast this union into the following:
typedef unsigned long long int UINT64;
The casting function I wrote is as follows:
UINT64 gtu64_to_uint64_cast(GT_U64 number_u)
{
UINT64 casted_number = 0;
casted_number = number_u.l[0];
casted_number = casted_number << 32;
casted_number = casted_number | number_u.l[1];
return casted_number;
}
This function is using the l member to perform the shifting and bitwise or. What will happen if the s or c members of the union are used to set its values?
I am not sure if this function will always cast the values correctly. I suspect it has something to do with the byte ordering of long and short. Can any body help?
Full example program is listed below.
#include <stdio.h>
typedef unsigned long GT_U32;
typedef unsigned short GT_U16;
typedef unsigned char GT_U8;
typedef union
{
GT_U8 c[8];
GT_U16 s[4];
GT_U32 l[2];
} GT_U64;
typedef unsigned long long int UINT64;
UINT64 gtu64_to_uint64_cast(GT_U64 number_u)
{
UINT64 casted_number = 0;
casted_number = number_u.l[0];
casted_number = casted_number << 32;
casted_number = casted_number | number_u.l[1];
return casted_number;
}
int main()
{
UINT64 left;
GT_U64 right;
right.s[0] = 0x00;
right.s[1] = 0x00;
right.s[2] = 0x00;
right.s[3] = 0x01;
left = gtu64_to_uint64_cast(right);
printf ("%llu\n", left);
return 0;
}
That's really ugly and implementation-dependent - just use memcpy, e.g.
UINT64 gtu64_to_uint64_cast(GT_U64 number_u)
{
UINT64 casted_number;
assert(sizeof(casted_number) == sizeof(number_u));
memcpy(&casted_number, &number_u, sizeof(number_u));
return casted_number;
}
First of all, please use the typedefs from "stdint.h" for such a purpose. You have plenty of assumptions of what the width of integer types would be, don't do that.
What will happen if the s or c members
of the union are used to set its
values?
Reading a member of a union that has been written to through another member may cause undefined behavior if there are padding bytes or padding bits. The only exception from that is unsigned char that may always be used to access the individual bytes. So access through c is fine. Access through s may (in very unlikely circumstances) cause undefined behavior.
And there is no such thing like a "correct" cast in your case. It simply depends on how you want to interpret an array of small numbers as one big number. One possible interpretation for that task is the one you gave.
This code should work independantly of padding, endianess, union accessing and implicit integer promotions.
uint64_t gtu64_to_uint64_cast (const GT_U64* number_u)
{
uint64_t casted_number = 0;
uint8_t i;
for(i=0; i<8; i++)
{
casted_number |= (uint64_t) number_u->c[i] << i*8U;
}
return casted_number;
}
If you can't change the declaration of the union to include an explicit 64-bit field, perhaps you can just wrap it? Like this:
UINT64 convert(const GT_U64 *value)
{
union {
GT_U64 in;
UINT64 out;
} tmp;
tmp.in = *value;
return tmp.out;
}
This does violate the rule that says you can only read from the union member last written to, so maybe it'll set your hair on fire. I think it will be quite safe though, don't see a case where a union like this would include padding but of course I could be wrong.
I mainly wanted to include this since just because you can't change the declaration of the "input" union doesn't mean you can't do almost the same thing by wrapping it.
Probably an easier way to cast is to use union with a long long member:
typedef unsigned long long int UINT64;
typedef unsigned long GT_U32;
typedef unsigned short GT_U16;
typedef unsigned char GT_U8;
typedef union
{
GT_U8 c[8];
GT_U16 s[4];
GT_U32 l[2];
UINT64 ll;
} GT_U64;
Then, simply accessing ll will get the 64-bit value without having to do an explicit cast. You will need to tell your compiler to use one-byte struct packing.
You don't specify what "cast the values correctly" means.
This code will cast in the simplest possible way, but it'll give different results depending on your systems endianness.
UINT64 gtu64_to_uint64_cast(GT_U64 number_u) {
assert(sizeof(UINT64) == sizeof(GT_U64));
return *(UINT64 *) &number_u;
}