About the data alignment in c [duplicate] - c

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 1 year ago.
And I define a struct :
#include <stdint.h>
#include <stdio.h>
#define O(type, field) (size_t)(&(((type *)0)->field))
struct byname {
int16_t int16;
int32_t int32;
int64_t int64;};
Then I use sizeof(struct byname) and it return 16 which I can understand.
However when I define the like adding a int8_t:
#include <stdint.h>
#include <stdio.h>
#define O(type, field) (size_t)(&(((type *)0)->field))
struct byname {
int16_t int16;
int32_t int32;
int64_t int64;
int8_t int8;};
It just return 24, I think a int8 only takes 1 by and there are 3 bys padding according to data alignment, so I think the answer should be 20.
Anyone can kindly explain to me how the 24 comes?

The structure contains int64_t. If the compiler thinks that int64_t should be aligned to 8-byte boundary, it is reasonable to make the size of the structure multiple of 8 (therefore 24 bytes instead of 20) to align every int64_t int64; in an array of struct byname to 8-byte boundary.

Related

BYTE, WORD and DWORD macros definition

I am trying to understand, what would be the best way to define BYTE, WORD and DWORD macros, which are mentioned in answers of this question.
#define LOWORD(l) ((WORD)(l))
#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
#define LOBYTE(w) ((BYTE)(w))
#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF))
Would it be correct to assume, that:
BYTE is macro defined as
#define BYTE __uint8_t
WORD is macro defined as
#define WORD __uint16_t
DWORD is macro defined as
#define DWORD __uint32_t
If yes, why cast to another macro instead of casting to __uint8_t, __uint16_t or __uint32_t? Is it written like that to increase clarity?
I also found another question which answers include typedef, with little bit more of research I've found answers to question about comparing #define and typedef. Would typedef be better to use in this case?
This is a portable solution:
#include <stdint.h>
typedef uint32_t DWORD; // DWORD = unsigned 32 bit value
typedef uint16_t WORD; // WORD = unsigned 16 bit value
typedef uint8_t BYTE; // BYTE = unsigned 8 bit value
You have it defined at: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx, and that is already defined in Windows Data Type headers for WinAPI:
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef unsigned long DWORD;
and it is a type, and not a macro.

Initializing pointer member within structure

I'm trying to write a module that will read a specific address value from a micro controller, the initialization code has compiled on its own but when I try to compile it within a structure it seem to complain. Are there restriction on initializing pointers within a structure?
#include <stdio.h>
#include <esper.h>
#include <stdlib.h>
#include <stdint.h>
#include "lmk04800.h"
#define NUM_MSS_GPIO 32
#define SEL_NIM 3
#define SOURCE_SEL 4
#define SEL_EXT 5
#define CLK0_3_EN 6
#define CLK4_7_EN 7
#define CLK8_11_EN 8
#define CLK12_15_EN 9
#define CLK16_19_EN 10
#define CLK20_23_EN 11
#define LMK_SYNC 12
typedef struct {
int fd_gpio[NUM_MSS_GPIO];
uint8_t data_gpio[NUM_MSS_GPIO];
uint32_t esata_freqCounter;
uint32_t ext_freqCounter;
uint32_t esata_trgCounter;
uint32_t ext_trgCounter;
tLMK04800 settings;
volatile uint32_t *freqCounter_addr;
volatile uint32_t *trgCounter_addr;
volatile uint32_t *manSync_addr;
freqCounter_addr = (volatile uint32_t *)0x30000000;
trgCounter_addr = (volatile uint32_t *)0x30000100;
manSync_addr = (volatile uint32_t *)0x30000200;
} tESPERModuleTest;
The compilation error I get is:
test/mod_test.h:32: error: expected specifier-qualifier-list before 'freqCounter_addr'
You can't define initial values for struct members when you define the type. It could be useful if it were permitted, and the initial values would be applied automatically to any objects of the type. C just doesn't permit it.
You can only initialize objects.
You've defined a type named tESPERModuleTest. If you want to define and initialize an object of that type, you can do something like this after defining the type (untested code):
tESPERModuleTest obj = {
.freqCounter_addr = (volatile uint32_t *)0x30000000,
.trgCounter_addr = (volatile uint32_t *)0x30000100,
.manSync_addr = (volatile uint32_t *)0x30000200
};
(The other members will be default zero-initialized, or you can provide values for them.)

How can I aligned struct as 4 bytes expicitly

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.

weird struct definition? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does 'unsigned temp:3' means
A struct's definition goes like this,
typedef struct
{
uint32_t length : 8;
uint32_t offset : 24;
uint32_t type : 8;
} A;
I haven't seen this kind of definition before, what does it mean by :8 and :24?
It's defining bitfields. This tells the compiler that length is 8 bits, offset is 24 bits and type is also 8 bits.
Refer the following link. They are bit-fields. http://www.cs.cf.ac.uk/Dave/C/node13.htmlhttp://en.wikipedia.org/wiki/Bit_field
#include <stdio.h>
typedef unsigned int uint32_t;
#pragma pack(push, 1)
typedef struct
{
uint32_t length : 8;
uint32_t offset : 24;
uint32_t type : 8;
} A;
typedef struct
{
uint32_t length;
uint32_t offset;
uint32_t type;
} B;
#pragma pack(pop)
int main()
{
printf("\n Size of Struct: A:%d B:%d", sizeof(A), sizeof(B));
return 0;
}
Structure A's size will be 5 Bytes where as B's size will be 12 bytes.
This notation defines bit fields, i.e. the size in number of bits for that structure variable.

Sizeof operator returns incorrect size? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
Extra bytes when declaring a member of a struct as uint32_t
For some reason, the sizeof operator returns a bogus size for this structure (48 instead of 40):
typedef struct mbdb_file_info {
uint16_t mode;
uint32_t unk0;
uint32_t unk1;
uint32_t user_id;
uint32_t group_id;
uint32_t time0;
uint32_t time1;
uint32_t time2;
uint64_t length;
uint8_t flag;
uint8_t property_count;
} mbdb_file_info;
So here is a simple test:
printf("%ld %ld %ld %ld: %ld", sizeof(uint8_t),
sizeof(uint16_t),
sizeof(uint32_t),
sizeof(uint64_t),
sizeof(mbdb_file_info));
Which prints:
1 2 4 8: 48
How does this happen? If you add all the sizes together you get 40, not 48. Where on earth does the 48 come from?
And if it's some weird x86-64 perk, how do I ensure that the all the fields of the structures occupy the amounts I want them to occupy (I'm casting a bunch of bytes to this structure)?
The compiler may append some bytes in the middle of the struct in order to align the struct members. The size of the struct is at least the sum of he members' size, but not limited to it.
You can also get rid of the padding by re-ordering your struct members. For example, if you declare the 64-bit, then 32's, then 16, then 8's, it will be naturally aligned and not have extra padding bytes.
Because of the structure padding (not sure which was the term here). The biggest field is 64bit, so everything's aligned according it. So, we have:
typedef struct mbdb_file_info {
uint16_t mode; // 16 +
uint32_t unk0; // 32 = 48, so add 16 more to align to 64bit;
uint32_t unk1; // this
uint32_t user_id; // and this give 64bits ;
uint32_t group_id; // again this
uint32_t time0; // plus this - 64bits;
uint32_t time1; // this
uint32_t time2; // and this = 64bit ;
uint64_t length; // this is 64 by itself
uint8_t flag; // this
uint8_t property_count; // +this is 16, add 48 for the alignment
} mbdb_file_info; // when you sum all bits (+ the additional for padding)
// you have exactly 48B
Alignment. Certain data types are aligned at certain boundaries (read: addresses divisible by a factor of 2, e.g. 16), dependent on the architecture, and this causes padding in the structure.
There are compiler options to suppress this behaviour, and the gcc documentation tells you how to use the aligned attribute for it.
This is called structure padding for alignment.
What is likely happening is that 8- and 16-bit values are padded to 32 bit and the whole structure is padded to be a multiple of machine word size (8).

Resources