below code snippet,How can we make below struct define as 4 bytes aligned?
I have tried pragma pack to aligned Explicitly.But It's does NOT work as we want...
#pragma pack(push)
#pragma pack(4)
//..struct devine here.
#pragma pack(pop);
I have tried __attribute__ to aligned Explicitly.It's also does NOT work as well..
struct device_info {
//
}__attribute__(packed);
//struct device_info dev_info;
sizeof (struct device_info)=211
I have tried __attribute__ to aligned Explicitly.It's also does NOT work as well..
struct device_info {
//
};
typedef struct device_info deice_info __attribute__(packed)
device_info dev_info;
sizeof (dev_info)=211
Question1:
How can I aligned struct device_info Explicitly,and offsetof output like below:
offsetof magic=0
offsetof is_unlocked=16
offsetof is_tampered=20
offsetof is_unlock_critical=24
offsetof charger_screen_enabled=28
offsetof display_panel=32
offsetof booloader_version=96
offsetof radio_version=160
offsetof verity_mode=224
offsetof is_origin=228
code snippet:
#define DEVICE_MAGIC_SIZE 13
#define MAX_PANEL_ID_LEN 64
#define MAX_VERSION_LEN 64
struct device_info{
unsigned char magic[DEVICE_MAGIC_SIZE];
bool is_unlocked;
bool is_tampered;
bool is_unlock_critical;
bool charger_screen_enabled;
char display_panel[MAX_PANEL_ID_LEN];
char booloader_version[MAX_VERSION_LEN];
char radio_version[MAX_VERSION_LEN;
bool verity_mode;
bool is_origin;
};
Update 1
I have tried below snippet
struct device_info{
__attribute__((__aligned(4))) bool is_unlock;
//...
};
It's same that work well.
Question two:
What's difference between
struct device_info{
__attribute__((__aligned(4))) bool is_unlock;
//...
};
and
struct device_info{
bool is_unlock;
//..
}__attribute__((__aligned(4))) ;
Question 3
How can we dump during source code compiled to execute binary or library?(preprocessing->Compile->link) objdump?or others?
Since C11 you can use the standard alignas specifier.
This should solve your question.
It would appear that in your implementation, sizeof(bool) is equal to 1. In that case, the padding rules are being correctly adhered to, so is_unlocked can appear precisely after magic with no additional padding.
The other thing is that bool is implementation-defined. Please read this post: Is sizeof(bool) defined?
What you might benefit more from, is to use proper types from <ctype.h> when you are laying out a structure with absolute sizes. If you want your bool values to be 32-bit integers, then use int32_t or uint32_t instead.
Related
Consider this typedef:
#pragma pack(4)
typedef struct
{
uint8 dataArea0[11];
uint8 dataArea1[12];
uint8 dataArea2[13];
uint8 dataArea3[14];
} myStruct;
I have some non-2^n sized arrays that I'd like to use from other libs. From those libs these dataAreas can be cast as e.g., structs or whatever i need. The problem occurs when one of these struct members land on a non 4-byte aligned address AND contain data types that are not happy about their address alignment.
Therefore I'd like to force the alignment with the pack pragma, but this does not help (at least in the IAR compiler -- from the manual: Use this pragma directive to specify the maximum alignment of struct and union members.). I also tried to use the data_alignment pragma, but this seems to be for variables and not struct members.
Does anyone know a nice compiler trick to force the alignment of the struct members?
Quicklink to compiler manual for those interested: IAR AVR32 Compiler Ref
Edit:
I ended up using this as an alternative
#define ROUND_UP_NEXT_FOUR(x) ((x + 3) & ~0x03)
typedef struct
{
uint8 dataArea0[ROUND_UP_NEXT_FOUR(11)];
uint8 dataArea1[ROUND_UP_NEXT_FOUR(12)];
uint8 dataArea2[ROUND_UP_NEXT_FOUR(13)];
uint8 dataArea3[ROUND_UP_NEXT_FOUR(14)];
} myStruct;
In this way I'm sure that the padding will take place at a 4-aligned address.
Edit2:
An example of how this can go wrong:
struct otherStruct
{
uint16 dataBuf0;
uint32 dataBuf1;
uint32 dataBuf2;
uint32 dataBuf3;
uint32 dataBuf4[10];
};
myStruct* myStructInstance = 0x00000000; //some address
//address of this is 0x0B
struct otherStruct* oS = (struct otherStruct*) myStructInstance.dataArea1;
//we assign to a 2 byte variable that is
//located at address that is not 2 byte aligned -> error!
os->dataBuf0 = 10;
In this case we get a runtime error (worst (or best?) case, crash).
Unfortunately the IAR AVR32 compiler does not support the _Alignas keyword. However, when IAR language extensions are enabled it supports anonymous unions and this can be used to force the alignment of individual fields of a struct. The trick is that the alignment of a union is the strictest (largest) alignment of any of its fields. Thus, by wrapping each field dataArea? in an anonymous union with a dummy field with 32-bit alignment it is possible to force the alignment of each dataArea? field to 32-bit. An example is shown below. It include both raw anonymous-union declarations as well as macro-magic to simplify declaration when the number of fields is large.
#include <stdint.h>
#define GLUE_B(x,y) x##y
#define GLUE(x,y) GLUE_B(x,y)
#define ALIGNED(FIELD, ALIGN_TYPE) union { FIELD; ALIGN_TYPE GLUE(a,__LINE__); }
#define ALIGNED32(FIELD) ALIGNED(FIELD, uint32_t)
typedef struct
{
ALIGNED(uint8_t dataArea0[11], uint32_t);
ALIGNED32(uint8_t dataArea1[12]);
union { uint8_t dataArea2[13]; uint32_t a2;};
union { uint8_t dataArea3[12]; uint32_t a3;};
} myStruct;
I have a struct
typedef struct
{
int A ;
int B ;
…
} SomeStruct ;
I have an instance of SomeStruct that I want to persist to Flash memory which has a sector size of 512 bytes. What GCC attribute can I apply to that instance such that the allocation size is a multiple of 512 bytes?
The only options I can think of are :-
1) Pad the struct to make it exactly 512 bytes. This requires recalculation every time a field is added to the struct. No compiler warnings when I get it wrong. Also struct is larger than needed with normal initialisation, copying etc.
2) Place the variable in a separate Linker section. This provides full protection and warnings, but gets a bit tedious if multiple variables are used.
3) Make a union of the struct and a 512 byte array. Copes with adding extra fields until the struct is greater than 512 bytes, then fails without any warnings.
Referring 1:
#include <assert.h>
#define FLASH_BYTES (512)
#pragma pack(1)
struct flash
{
struct data
{
int i;
char c;
...
};
char pads[FLASH_BYTES - sizeof (struct data)];
};
#pragma pack()
int main(void)
{
assert(sizeof (struct flash) == FLASH_BYTES);
...
The assert might even not be necessary because if the result
FLASH_BYTES - sizeof (struct data)
is negative any GCC should issue an error. To make sure it will be negative cast the result of the sizeof operation to any signed integer, like for example so:
FLASH_BYTES - (int) sizeof (struct data)
So trying to compile this
#pragma pack(1)
struct flash
{
struct data
{
int i;
char c[FLASH_BYTES];
};
char pads[FLASH_BYTES - (int) (sizeof (struct data))];
};
#pragma pack()
int main(void)
{
}
You should be giving you something like:
main.c:14:12: error: size of array ‘pads’ is negative
char pads[FLASH_BYTES - (int) sizeof (struct data)];
A portable solution is to define a union of SomeStruct, with a char array whose size is calculated to meet the necessary alignment.
typedef struct
{
int A;
int B;
char c[512];
} SomeStruct;
#define STORAGE_ALIGNMENT 512
typedef union
{
SomeStruct data;
char paddedData[((sizeof(SomeStruct) + STORAGE_ALIGNMENT - 1) / STORAGE_ALIGNMENT) * STORAGE_ALIGNMENT];
} SomeStructAligned;
Online running version (Coliru) here
The sizing formula is well known and works for any integer. Since this is a power-of-2 you could also simplify it down to the form (sizeof(SomeStruct) + (STORAGE_ALIGNMENT - 1)) & ~(STORAGE_ALIGNMENT - 1)) == (sizeof(SomeStruct) + 0x1ff) & ~0x1ff). In practice you may need ~size_t(0x1ff) on the rightmost term to ensure portability to 64-bit machines; since 0x1ff is an int (32-bit), ~0x1ff results in a 64-bit 0x00000000fffffe00 value instead of the desired 0xFFFFFFFFfffffe00 mask.
Sub-Optimal Approach
An alternative approach could have been to define a wrapper struct containing your original data plus some automatically calculated padding.
typedef struct
{
int A;
int B;
} SomeStruct;
#define STORAGE_ALIGNMENT 512
typedef struct
{
SomeStruct data;
char padding[(STORAGE_ALIGNMENT) - (sizeof(SomeStruct) % STORAGE_ALIGNMENT)];
} SomeStructAligned;
Online running version (Coliru) here.
However, the above is not perfect: if sizeof(SomeStruct) is a multiple of 512, then sizeof(padding) will be 512, wasting a quantum of storage. Whereas the union never wastes space.
You can try something like this (though it is a dirty bit trick)
#define ROUND_UP_512(x) ((x) + 511 & ~511)
struct myStruct {
// put whatever
};
union myUnion{
myStruct s;
char ensureSize[ROUND_UP_512(sizeof(myStruct))];
};
in this case the size of "myUnion" is guaranteed to be a multiple of 512 that is greater than or equal to the size of "myStruct"
I have defined two data structures that must remain the same size as each other for the application to function properly. The struct's are used to communicate between a PC and a DSP. The DSP code is in 'C', the PC side in C++.
for example:
struct inbound_data{
int header[5];
float val1;
float val2;
int trailer[3];
};
struct outbound_data{
int header[5];
int reply1;
int reply2;
float dat1;
float dat2;
int filler[1];
}
later I will do something like:
int tx_block[sizeof(outbound_data)];
int rx_block[sizeof(inbound_data)];
These arrays will be passed to the communication peripherals to transmit and receive between the devices.
Because of how the hardware works, it is essential that the size of the two structs match, so that the buffers are of equal size. This is easy enough to assure with proper care, but occasionally through the design cycle, the data structures get modified. If one is not extremely careful, and aware of the requirement that the structures stay the same size (and be reflected in the PC side code as well), chaos ensues.
I would like to find a compile time way to have the code not build if one of the structures gets modified so that it does not match the size of the other structure.
Is this possible somehow in 'standard' C to check the sizes at compile time and fail if they are different? (I think my compiler is at least C99, maybe not 11).
If you must use C99, then I too like Swordfish would suggest a macro. The way to make one which can appear anywhere, and would not introduce any objects for the optimizer to remove, is to put the invalid array in a typedef. So a more general purpose static assertion would look this:
#define CONCAT_(A,B) A##B
#define CONCAT(A,B) CONCAT_(A,B)
#define MY_STATIC_ASSERT(p, msg) typedef char CONCAT(dummy__,__LINE__) [(p) ? 1 : -1]
It's designed to mimic _Static_assert. The message is passed in with the hopes of a compiler diagnostic showing it. An example for its usage is here.
Which produces:
main.cpp:4:54: error: size of array 'dummy__13' is negative
#define MY_STATIC_ASSERT(p, msg) typedef char CONCAT(dummy__,__LINE__) [(p) ? 1 : -1]
^~~~~~~
main.cpp:2:22: note: in definition of macro 'CONCAT_'
#define CONCAT_(A,B) A##B
^
main.cpp:4:47: note: in expansion of macro 'CONCAT'
#define MY_STATIC_ASSERT(p, msg) typedef char CONCAT(dummy__,__LINE__) [(p) ? 1 : -1]
^~~~~~
main.cpp:13:1: note: in expansion of macro 'MY_STATIC_ASSERT'
MY_STATIC_ASSERT(sizeof(struct foo) == sizeof(struct baz), "Do not match!");
And all the way down there you can see the static assertion with the message.
As an afterthought, you can change dummy__ to please_check_line_ will will produce the more descriptive please_check_line_13 above.
The C11 Standard added a new keyword _Static_assert. You can use it to test a predicate at compile-time, and produce an error if it is false:
_Static_assert(sizeof(outbound_data) == sizeof(inbound_data), "sizes must match");
Enforce two structs have same size at compile time?
There is no standard way to enforce this in C. There are only ways to protect it from happening, such as static_assert - which prevents buggy code from compiling but doesn't solve the actual problem.
In your case there are several problems:
Your struct is using the naive default types of C. These aren't portable and can have any size. This can easily be fixed by swapping int for int32_t etc.
Endianess might make the code non-portable regardless of integer type. That's a separate issue that I won't address here, but it needs to be considered, especially for exotic DSPs.
Any struct can contain padding bytes anywhere, to sate system-specific alignment requirements. The root of the problem being that alignment works differently on different systems. This is the hard one to solve.
The dirty fix to avoid padding is to use static_assert together with some non-standard solution to ensure that the struct has the expected size. Such as #pragma pack(1) or gcc __attribute__ ((__packed__)) etc. These are not standard nor are they portable. Furthermore, skipping padding can be problematic on many systems and you can get issues with misaligned access - padding is there for a reason. So this can potentially create more problems than it solves.
So unfortunately we end up with the realisation that struct is unsuitable for portable code. Particularly for things like data protocol specifications.
If you need truly portable, rugged code, it leaves you with only one option, namely to use a raw data array of uint8_t. In case you need to translate this array into structs, you will have to write serialization/de-serialization code. Which will cost run-time overhead. But there's no other way around it, if you want truly portable structs.
For C99 you could use something like
#define C_ASSERT(x, y) { int dummy[(x) == (y) ? 1 : -1]; (void*)dummy; }
struct foo {
int f;
};
struct bar {
int b1;
//int b2;
};
int main()
{
C_ASSERT(sizeof(struct foo), sizeof(struct bar));
}
you can add padding to equalize the size
struct inbound_data;
struct outbound_data;
struct _inbound_data{
int header[5];
float val1;
float val2;
int trailer[3];
};
struct _outbound_data{
int header[5];
int reply1;
int reply2;
float dat1;
float dat2;
int filler[1];
};
struct inbound_data{
int header[5];
float val1;
float val2;
int trailer[3];
char padding[sizeof(struct _inbound_data) < sizeof(struct _outbound_data) ? sizeof(struct _outbound_data) - sizeof(struct _inbound_data) : 0];
};
struct outbound_data{
int header[5];
int reply1;
int reply2;
float dat1;
float dat2;
int filler[1];
char padding[sizeof(struct _outbound_data) < sizeof(struct _inbound_data) ? sizeof(struct _inbound_data) - sizeof(struct _outbound_data) : 0];
};
I it can be of course written shorter way without the struct members duplication - but I did it intentionally to show the idea.
struct inbound_data1 __attribute__((packed){
struct _inbound_data id;
char padding[sizeof(struct _inbound_data) < sizeof(struct _outbound_data) ? sizeof(struct _outbound_data) - sizeof(struct _inbound_data) : 0];
};
struct outbound_data1 __attribute__((packed){
struct _outbound_data od;
char padding[sizeof(struct _outbound_data) < sizeof(struct _inbound_data) ? sizeof(struct _inbound_data) - sizeof(struct _outbound_data) : 0];
};
FYI: This is my first question using stackoverflow!
The code is as follows:
uint8_t TestVar1;
uint8_t TestVar2;
typedef struct
{
uint8_t member1;
uint32_t member2;
}Test1;
typedef struct
{
uint8_t member1;
uint8_t member2[4];
}Test2;
Test1 TestStruct1;
Test2 TestStruct2;
TestVar1 = sizeof(TestStruct1); /*size is 8*/
TestVar2 = sizeof(TestStruct2); /*size is 5*/
I thought I understood padding but I can't explain TestVar2. I can explain TestVar1 being 8 bytes because there is 3 padding bytes as part of uint8_t member1.
However, with struct test2 are there no padding bytes? (Apparently not) Could someone provide some insight as to what is happening in struct test2 case?
As a side note, I am aiming for 5 bytes but I don't know why the second case works. Is the array breaking down to a pointer or something? Is this safe(standard practice) to do?
Thanks!
uint8_t has no specific alignment requirements and thus does not require any padding to align it while uint32_t, being a multi-byte type, will want to be aligned on a 4-byte boundary. If you absolutely must have a struct with a uint8_t and uint32_t that takes only 5 bytes, you can use __attribute__((packed)) to tell the compiler to forego the padding (which I would carefully consider whether the space saved is worth misalignment):
typedef struct __attribute__((packed)) {
uint8_t member1;
uint32_t member2;
}test;
Another thing to consider is the ordering of the struct members. To keep a reduced struct size, put the largest members at the beginning of the struct as they will have the strictest alignment needs. Consider the following:
typedef struct {
uint8_t w;
uint32_t x;
uint8_t y;
uint32_t z;
}test2;
typedef struct {
uint32_t x;
uint32_t z;
uint8_t w;
uint8_t y;
}test3;
In order to keep the uint32_t members aligned, test2 will put padding after w and y, while test3 will already have the uint32_t members aligned and only put enough padding at the end of the struct so that the next free memory segment aligns with a 4-bytes boundary (as that is the strictest boundary of any of the struct's members). Therefore test2 will have a size of 16 bytes while test3 will have a size of 12 bytes.
Note: I have not seen where, if at all, this is defined in the C specs, but the results hold true for both gcc and clang in my tests.
In the (old) Linux source code (written in C89), a #define occurs that is used as a literal in the initialization of a structure (ide_pci_device_s) using the standard C89 struct literal initializer syntax, however, when I compile with a compiler that supports C99, I get the error initializer element is not constant, below is a sample of the code I am working with which throws the error.
#define ON_BOARD 1
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e
#define DEVID_PIIXa ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0})
typedef char byte;
typedef struct ide_pci_devid_t {
int one, two;
} ide_pci_devid_t;
typedef struct ide_hwif_t {
int whatever;
} ide_hwif_t;
typedef struct ide_pci_enablebit_s {
byte reg; /* byte pci reg holding the enable-bit */
byte mask; /* mask to isolate the enable-bit */
byte val; /* value of masked reg when "enabled" */
} ide_pci_enablebit_t;
typedef struct ide_pci_device_s {
ide_pci_devid_t devid;
const char *name;
void (*init_hwif)(ide_hwif_t *hwif);
ide_pci_enablebit_t enablebits[2];
byte bootable;
unsigned int extra;
} ide_pci_device_t;
static ide_pci_device_t ide_pci_chipsets[] = {
// HERE is where it says 'non-const initializer
{DEVID_PIIXa, "PIIX", NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
};
How can I still use the value of the #define while minimally altering the structure of the source to build with a C99 compiler?
The problem is the cast in:
#define DEVID_PIIXa ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0})
Your compiler thinks that makes it non-constant. Since where you're using the initializer is initializing a nested ide_pci_devid_t struct, you don't need the cast. Changing that define to:
#define DEVID_PIIXa {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0}
will fix it.
(Lifted to an answer from the comment discussion.)