I'm working with an struct compiled for a 32bit ARM processor.
typedef struct structure {
short a;
char b;
double c;
int d;
char e;
}structure_t;
If I use nothing, __attribute__ ((aligned (8))) or__attribute__ ((aligned (4))) I get the same results in terms of structure size and elements offset. Total size is 24. So I think it is always aligning to 8 (offsets are for both a=0 , b=2, c=8, d=16, e=20).
Why is 8 the default alignment chosen by the compiler? Should not it be 4 because is a 32 word processor?
Thanks in advance mates.
The aligned attribute only specifies a minimum alignment, not an exact one. From gcc documentation:
The aligned attribute can only increase the alignment; but you can decrease it by specifying packed as well.
And the natural alignment of double is 8 on your platform, so that is what is used.
So to get what you want you need to combine the aligned and packed attributes. With the following code, c has offset 4 (tested using offsetof).
typedef struct structure {
short a;
char b;
__attribute__((aligned(4))) __attribute__((packed)) double c;
int d;
char e;
} structure_t;
Related
I've read this about structure padding in C:
http://bytes.com/topic/c/answers/543879-what-structure-padding
and wrote this code after the article, what should print out size of 'struct pad' like 16 byte and the size of 'struct pad2' should be 12. -as I think.
I compiled this code with gcc, with different levels of optimization, even the sizeof() operator gives me both of them 16 byte.
Why is it?
This information is necessary for me because of PS3 machines, where the byte boundaries and exploitation of the full dma transfer is important:
#include <stdio.h>
#include <stdlib.h>
struct pad
{
char c1; // 1 byte
short s1; // 2 byte
short s2; // 2 byte
char c2; // 1 byte
long l1; // 4 byte
char c3; // 1 byte
};
struct pad2
{
long l1;
short s1;
short s2;
char c1;
char c2;
char c3;
};
int main(void)
{
struct pad P1;
printf("%d\n", sizeof(P1));
struct pad P2;
printf("%d\n", sizeof(P2));
return EXIT_SUCCESS;
}
There are two tricks that can be used to owercome this problem
Using directive #pragma pack(1) and then #pragma pack(pop)
example:
#pragma pack(1)
struct tight{
short element_1;
int *element_2;
};
#pragma pack(pop)
To check if the sizes of two structs are same during compilation use this trick
char voidstr[(sizeof(struct1)==sizeof(struct2)) - 1]; //it will return error at compile time if this fail
Your structures each include a long, which your platform apparently requires to be on a four-byte boundary. The structure must be at least as aligned as its most aligned member, so it has to be 4-byte aligned, and a structure's size has to be a multiple of its alignment in case it goes into an array.
Extra padding is required to make the long aligned, and so the smallest multiple of 4 is 16.
Two pieces of advice:
You can compute the offset of a field l1 by
printf("Offset of field %s is %d\n", "l1", offsetof(struct pad, l1);
To get the offsetof macro you will need to #include <stddef.h> (thanks caf!).
If you want to pack data as densely as possible, use unsigned char[4] instead of long and unsigned char[2] instead of short, and do the arithmetic to convert.
EDIT:: The sizeof(struct pad2) is 12. Your code has a bug; structure P2 is declared of type struct pad. Try this:
#define xx(T) printf("sizeof(" #T ") == %d\n", sizeof(T))
xx(struct pad);
xx(struct pad2);
P.S. I should definitely stop trying to answer SO questions after midnight.
On PS3, don't guess. Use __attribute__((aligned (16))), or similar. Not only does it guarantee that the start of the structure will be aligned on a proper boundary (if global or static), it also pads the structure to a multiple of your specified alignment.
Your code isn't showing what you think it is, because both P1 and P2 are defined as instances of struct pad. struct pad2 isn't ever used.
If I change the definition of P2 so that it is struct pad2, gcc does indeed decide to make it size 12.
struct pad P1;
printf("%d\n", sizeof(P1));
struct pad P2;
printf("%d\n", sizeof(P2));
P1 and P2 have the same type "struct pad" maybe you want to use "struct pad2" for P2.
All CPU expect that the built in data types like (int, float,char,double) are stored in the memory at their natural boundary, at address of their length.So structure padding is done to faster access of data from memory.
For example,
If int is declared, it should occurs in the memory at an address multiple of 4, as
size of the int is 4 byte.
Similarly for double, it resides in memory at multiple of 8.
If memory is properly aligned, CPU can run faster and work efficiently.
For the following examples, let us assume:
Sizeof(int)=4 byte
Sizeof(float)=4 byte
Sizeof(char)=1 byte
Find details on BoundsCheck
I have an array of structs which i wish to store as cache aligned. I have read about the __CACHELINE_ALIGNED__ and __cacheline_aligned macros. now I wish to confirm that an array of a structs defined with this attribute are truely cache aligned.
struct test{
int val1;
int val2;
int val3;
} __CACHELINE_ALIGNED__;
struct test tArr[2];
of course if i will print the size of tArr[0] i will get 12 so i came up with the following test:
printf("size of first %p, second %p\n", &tArr[0], &tArr[1]);
And I receive pointers located 12 byte apart. Does that mean that the structs are not cache aligned? how can i verify that the lines are really cache aligned.
thanks.
There is nothing called __CACHELINE_ALIGNED__ in standard C, where did you read about it? You are just defining a global variable called __CACHELINE_ALIGNED__ with you code.
If you want your structure to be cache line aligned you have to specify the alignment in a way that is standard for your compiler. For instance assuming 64 byte cache line and GCC you would go:
struct test{
int val1;
int val2;
int val3;
} __attribute__ ((aligned (64)));
I am working with bit-fields in C and do not understand what is going on with them. I created this code but I do not understand why different things are coming up as usual.
struct tB
{
unsigned b1:3;
signed b2:6;
unsigned b3:11;
signed b4:1;
} b;
int main(void)
{
struct tB *p;
printf("%d\n", sizeof(*p));
}
Why when I print out *p do I get 4 as *p?
Let us say I was trying to get sizeof(b), how would I come up with that?
sizeof(b) will give you the size in bytes of a variable of type struct tB,which in this case will be 4 (Due to padding it won't be 3 as it is expected to be)
sizeof(*p) will again give you the size in bytes of a variable of type struct tB .You should initialize p with the address of a variable of struct tB type.Eg:
struct tB *p=&b;
But you should know that in this case if you use sizeof(p) then it would give the size of the pointer p, not the variable pointed by p. Try this variation of your program :
#include<stdio.h>
struct tB
{
unsigned b1:3;
signed b2:6;
unsigned b3:11;
signed b4:1;
unsigned b5:13;
} b;
int main(void)
{
struct tB *p;
printf("%d\n%d",sizeof(*p),sizeof(p));
}
Here is another variation that rounds the size of struct tB to 24 bits(3 bytes) as you expect,by dealing with the padding using the #pragma pack() directive,which is compiler dependent (I am using CodeBlocks on Windows).
#include<stdio.h>
#pragma pack(1)
struct tB
{
unsigned b1:3;
signed b2:6;
unsigned b3:11;
signed b4:1;
} b;
int main(void)
{
struct tB *p;
printf("%d\n%d",sizeof(*p),sizeof(p));
}
You have 21 bits, round up to nearest int and you got 32 (i.e. 4 bytes).
It's all about processor word. The processor accessing the memory can't access it, let's say, 1 or 2 bytes. It fetching it by word. Generally, compiler makes proper aligning of structures to conform word alignment. Usually, this alignment is equal to processor architecture though the size of processor register. So, in your case you have 21-bit structure which aligned to one word. If you will adjust your structure to be, say, 33-bits long you will have 2-word alignment and in your case program will print 8.
Here the article on Wikipedia related to this Data structure alignment.
I am using ARM. I got alignment fault due to read/write in odd offset(we knew ARM is 4 byte aligned). All the structs defined in my program is single - byte aligned like
#pragma pack(push, 1)
typedef struct
{
char a1;
int a2;
char a3;
}a;
#pragma pack(pop)
I am trying to do
#pragma pack(push, 1)
typedef struct
{
char a1 __attribute__ ((aligned (4)));
int a2;
char a3;
}a;
#pragma pack(pop)
the gcc attribute _attribute_ ((aligned (4))) makes no effect.
Note :: The above code is not my actual code. sample scenario.
so I re-arranged structure member to solve the alignment issue. I want to ensure whether the re-arranging is the possible solution or we can make _attribute_ to work on this scenario. Any other solutions are welcome. Thanks in advance.
You can safely read/write char/int in byte-aligned structs on ARM, compiler take care about alignment. Single problem can occur with alignment issue is with the casting to 32 bit int like this:
char buf[5];
char *p = buf + 1;
*((int *)p) = 1;
Note: if you for some reasons like align some member (from begin of the struct) you can use following trick:
typedef struct {
struct {} __attribute__ ((aligned (4)));
char a1; // offset is 4
int a2; // offset is 5
char a3; // offset is 9
} a;
I've read this about structure padding in C:
http://bytes.com/topic/c/answers/543879-what-structure-padding
and wrote this code after the article, what should print out size of 'struct pad' like 16 byte and the size of 'struct pad2' should be 12. -as I think.
I compiled this code with gcc, with different levels of optimization, even the sizeof() operator gives me both of them 16 byte.
Why is it?
This information is necessary for me because of PS3 machines, where the byte boundaries and exploitation of the full dma transfer is important:
#include <stdio.h>
#include <stdlib.h>
struct pad
{
char c1; // 1 byte
short s1; // 2 byte
short s2; // 2 byte
char c2; // 1 byte
long l1; // 4 byte
char c3; // 1 byte
};
struct pad2
{
long l1;
short s1;
short s2;
char c1;
char c2;
char c3;
};
int main(void)
{
struct pad P1;
printf("%d\n", sizeof(P1));
struct pad P2;
printf("%d\n", sizeof(P2));
return EXIT_SUCCESS;
}
There are two tricks that can be used to owercome this problem
Using directive #pragma pack(1) and then #pragma pack(pop)
example:
#pragma pack(1)
struct tight{
short element_1;
int *element_2;
};
#pragma pack(pop)
To check if the sizes of two structs are same during compilation use this trick
char voidstr[(sizeof(struct1)==sizeof(struct2)) - 1]; //it will return error at compile time if this fail
Your structures each include a long, which your platform apparently requires to be on a four-byte boundary. The structure must be at least as aligned as its most aligned member, so it has to be 4-byte aligned, and a structure's size has to be a multiple of its alignment in case it goes into an array.
Extra padding is required to make the long aligned, and so the smallest multiple of 4 is 16.
Two pieces of advice:
You can compute the offset of a field l1 by
printf("Offset of field %s is %d\n", "l1", offsetof(struct pad, l1);
To get the offsetof macro you will need to #include <stddef.h> (thanks caf!).
If you want to pack data as densely as possible, use unsigned char[4] instead of long and unsigned char[2] instead of short, and do the arithmetic to convert.
EDIT:: The sizeof(struct pad2) is 12. Your code has a bug; structure P2 is declared of type struct pad. Try this:
#define xx(T) printf("sizeof(" #T ") == %d\n", sizeof(T))
xx(struct pad);
xx(struct pad2);
P.S. I should definitely stop trying to answer SO questions after midnight.
On PS3, don't guess. Use __attribute__((aligned (16))), or similar. Not only does it guarantee that the start of the structure will be aligned on a proper boundary (if global or static), it also pads the structure to a multiple of your specified alignment.
Your code isn't showing what you think it is, because both P1 and P2 are defined as instances of struct pad. struct pad2 isn't ever used.
If I change the definition of P2 so that it is struct pad2, gcc does indeed decide to make it size 12.
struct pad P1;
printf("%d\n", sizeof(P1));
struct pad P2;
printf("%d\n", sizeof(P2));
P1 and P2 have the same type "struct pad" maybe you want to use "struct pad2" for P2.
All CPU expect that the built in data types like (int, float,char,double) are stored in the memory at their natural boundary, at address of their length.So structure padding is done to faster access of data from memory.
For example,
If int is declared, it should occurs in the memory at an address multiple of 4, as
size of the int is 4 byte.
Similarly for double, it resides in memory at multiple of 8.
If memory is properly aligned, CPU can run faster and work efficiently.
For the following examples, let us assume:
Sizeof(int)=4 byte
Sizeof(float)=4 byte
Sizeof(char)=1 byte
Find details on BoundsCheck