Bit field in C; bytes and bits [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 2 years ago.
I have found the following example:
#include <stdio.h>
// Space optimized representation of the date
struct date {
// d has value between 1 and 31, so 5 bits
// are sufficient
unsigned int d : 5;
// m has value between 1 and 12, so 4 bits
// are sufficient
unsigned int m : 4;
unsigned int y;
};
int main()
{
printf("Size of date is %lu bytes\n", sizeof(struct date));
struct date dt = { 31, 12, 2014 };
printf("Date is %d/%d/%d", dt.d, dt.m, dt.y);
return 0;
}
The results are
Size of date is 8 bytes
Date is 31/12/2014
I cant understand the first result. Why is it 8 bytes?
My thoughts:
y is 4 bytes, d is 5 bits and m is 4 bits. The total is 4 bytes and 9 bits. 1 byte is 8 bits, then the total is 41 bits.

There is a very good explanation here
C automatically packs the above bit fields as compactly as possible, provided that the maximum length of the field is less than or equal to the integer word length of the computer. If this is not the case then some compilers may allow memory overlap for the fields whilst other would store the next field in the next word (see comments on bit fiels portability below).

Related

C Sizeof char[] in struct [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I know what padding is and how alignment works. Given the struct below:
typedef struct {
char word[10];
short a;
int b;
} Test;
I don't understand how C interprets and aligns the char array inside the struct. It should be 9 chars + terminator and it should be regarded as the longest like this:
| - _ - _ - _ - _ - word - _ - _ - _ - _ - |
| - a - | - _ - b - _ - | padding the remaining 4 bytes
The "-" represents a byte and "_" separates the bytes. So we have the 10 bytes long word, the 2 bytes long a and the 4 bytes long b and padding of 4 bytes. But when I print sizeof(Test) it returns 16.
EDIT: I got it.
In a struct like
struct {
char word[10];
short a;
int b;
}
you have the following requirements:
a needs an even offset. As the char arry before it has an even length, there is no need for padding. So a sits at offset 10.
b needs an offset which is dividible by 4. 12 is dividible by 4, so 12 is a fine offset for b.
The whole struct needs a size which is dividible by 4, because every b in an array of this struct needs to have the said requirement. But as we are currently at size 16, we don't need any padding.
WWWWWWWWWWAABBBB
|-- 10 --| 2 4 = 16
Compare this with
struct {
char word[11];
short a;
int b;
}
Here, a would have offset 11. This is not allowed, thus padding is inserted. a is fine with an offset of 12.
b would then get an offset of 14, which isn't allowed either, so 2 bytes are added. b gets an offset of 16. The whole struct gets a size of 20, which is fine for all subsequent items in an array.
WWWWWWWWWWW.AA..BBBB
|-- 11 --|1 2 2 4 = 20
Third example:
struct {
char word[11];
int b;
short a;
}
(note the changed order!)
b is happy with an offset of 12 (it gets 1 padding byte),
a is happy with an offset of 16. (no padding before it.)
After the struct, however, 2 bytes of padding are added so that the struct aligns with 4.
WWWWWWWWWW..BBBBAA..
|-- 10 --| 2 4 2 2 = 20
In:
struct
{
char word[10];
short a;
int b;
}
and given two-byte short and four-byte int, the structure is laid out in memory:
Offset Member
0 word[0]
1 word[1]
2 word[2]
3 word[3]
4 word[4]
5 word[5]
6 word[6]
7 word[7]
8 word[8]
9 word[9]
10 a
11 a
12 b
13 b
14 b
15 b
To get the layout described in the question, where a and b overlap word, you need to use a struct inside a union:
typedef union
{
char word[10];
struct { short a; int b; };
} Test;
Generally, each variable will be aligned on a boundary of its size.
(unless attributes such as packed are applied)
A complete discussion is on Wikipedia, which says in part:
A char (one byte) will be 1-byte aligned.
A short (two bytes) will be 2-byte aligned.
An int (four bytes) will be 4-byte aligned.
A long (four bytes) will be 4-byte aligned.
A float (four bytes) will be 4-byte aligned.
A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on
Linux (8-byte with -malign-double compile time option).
A long long (eight bytes) will be 4-byte aligned.
So your structure is laid out as:
typedef struct {
char word[10];
// Aligned with beginning of structure; takes bytes 0-9
short a;
// (assuming short is 2-bytes)
// Previous member ends on byte 9, this one starts on byte-10.
// Byte 10 is a multiple of 2, so no padding necessary
// Takes bytes 10 and 11
int b;
// Previous member ends on byte 11, next byte is 12, which is a multiple of 4.
// No padding necessary
// Takes bytes 12, 13, 14, 15.
} Test;
Total size: 16 bytes.
If you want to play with it, change your word-array to 9 or 11 bytes,
or reverse the order of your short and int, and you'll see the size of the structure change.

It will give the output 28 on DEV c++ compiler I am expecting 26 considering float as 4 byte int as 4 byte and char as 1 byte [duplicate]

This question already has answers here:
Structure padding and packing
(11 answers)
Closed 7 years ago.
struct
{
int m,s,l;
union
{
char c[10];
};
float p;
} a;
int main()
{
printf("%d",sizeof(a));
return 0;
}
according to the calculations ans must be 4*3+10+4=26 but DEV C++ compiler showing the output 28.
The principles of allocating local variables on stack are roughly the same for all systems
1 -- Stack grows from high addresses to low addresses
2 -- The order of declaration of your variables in your program corresponds to growth of stack
3 -- Each type has alignment - the address of any variable must be divisible by its size (1 for char, 2 for short, etc).Try to waste as little space as possible
In this way, we try to use some waste space to improve the speed of memory access.
So in your codes, it meams that
#include <stdio.h>
#include <stdlib.h>
struct // the base address is &a
{
int m; // [0, 4)
int s; // [4, 8)
int l; // [8, 12)
union
{
char c[10]; // [12, 22)
};
// char m_align[2] // there are 4 byte for align
float p; // [24, 28)
}a; // sizeof = 28
the value m is begin at the start of type a, and occupancy 4 byte in 32bit system, so it's address is [0, 4). and it's start address can divisible by sizeof(int).
this is the same to s and l.
and then the union value c[10] occupancy, occupancy [12, 22), the begining od it's address 12 can divisible by sizeof(int).
What's importment the next address is 22, and the value p will occupancy sizeof(float) = 4 bytes,but the address 22 can't divisible by sizeof(float). we must fill the space to alignment the struct and try to waste as little space as possible. So the base address of value p will be 24 which can divisible by sizeof(float), so the adddress of p is [24, 28]...
you can see this https://en.wikipedia.org/wiki/Data_structure_alignment for detail
The members in the structure arranged as a group of 4 bytes in 32 bit processor.So you are getting 28 bytes as size.
for more details see here
It is due to padding

How is sizeof structures found? [duplicate]

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 9 years ago.
I am getting 56 bytes for the following. Can anyone explain how is that?
#include <stdio.h>
typedef struct how_many_bytes {
long s[4];
char c, e;
int i[2];
char *d;
} How_Many_Bytes;
int main(){
printf("%lu ", sizeof(How_Many_Bytes));
}
Shouldn't it be (4*8) + 1 + 1 + 2(for padding) + 4 + 4 + 8 = 52 bytes
Because it's a 64-bit machine, so the padding is 6 instead of 2 in your calculation.
Also, you should use %zu to print size_t.
Your analysis is correct, except that there is an additional 4 bytes padding before the char *d member. This is so that the d member is aligned on an 8-byte boundary.
The pahole output for this structure on x86-64 is:
struct how_many_bytes {
long int s[4]; /* 0 32 */
char c; /* 32 1 */
char e; /* 33 1 */
/* XXX 2 bytes hole, try to pack */
int i[2]; /* 36 8 */
/* XXX 4 bytes hole, try to pack */
char * d; /* 48 8 */
/* size: 56, cachelines: 1 */
/* sum members: 50, holes: 2, sum holes: 6 */
/* last cacheline: 56 bytes */
}; /* definitions: 1 */
No matter how you rearrange the members of this structure, you won't be able to do better than 6 bytes in total of padding. The sum of the sizes of the members is 50 bytes, and the maximum alignment of the structure members is 8, so even if you arrange the members in the optimal order there will be 6 bytes of padding at the end of the structure to round its size up to the next biggest multiple of 8.

union: strange behavior [c]

It is said: "A union is a special class type that can hold only one of its non-static data members at a time." (http://en.cppreference.com/w/cpp/language/union)
But how can it hold more that one member?
y is of 8 bytes and x is of 4 bytes. The size of union is the size of the MAX element (8 bytes). It cannot hold 4 + 8 = 12 bytes...
I'm confused.
#include <stdio.h>
#include <stdlib.h>
union number {
int x;
double y;
};
int main()
{
union number value;
// ok
value.x = 1;
printf("\n int: %5d\ndouble: %f\n", value.x, value.y);
// ok
value.y = 1.0;
printf("\n int: %5d\ndouble: %f\n", value.x, value.y);
// NOT OK! But if I swap `value.x and value.y` it will work properly...
value.y = 1.0;
value.x = 1;
printf("\n int: %5d\ndouble: %f\n", value.x, value.y);
return 0;
}
The output is
The union allocates enough memory for the "largest" datatype.
As an example, If union would contain uint8_t a, uint16_t b. The data would align as follow
Bits LSB 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 MSB
Uint8_t a -------------->
Uint16_t b ------------------------------------>
Var b= 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 in binary
And If you look at var a. It will give you in binary 00000001, 128 in decimal.
`
O well, I dont know if I confused you even more now :).
A union can have as many members as you want, but only one member at a time is valid. This is because all members of a union shares the same memory. So if you change one member, then the others will change as well. However, assigning to one member, and then access another may not produce the results you expect, since often the layout in memory is different. This is the case of int and double, one can't be used as another.
What you're looking for is a structure:
struct number
{
int x;
double y;
};
The above contain two separate members, that can both be used at the same time as they no longer share the same memory.

To Obtain EPOCH Time Value from a Packed BIT Structure in C

I need to find out the Epoch time from a binary data file which has following data structure (it is a 12 byte structure):
Field-1 : Byte 1, Byte 2, + 6 Bits from Byte 3
Time-1 : 2 Bits from Byte 3 + Byte 4
Time-2 : Byte 5, Byte 6, Byte 7, Byte 8
Field-2 : Byte 9, Byte 10, Byte 11, Byte 12
For Field-1 and Field-2 I do not have issue as they can be taken out easily.
I need time value in Epoch Time (long) as it has been packed in Bytes 5,6,7,8 and 3 and 4 as follows:
Bytes 5 to 8 (32 bit word) Packs time value bits from 0 thru 31 (byte 5 has 0 to 7 bits,
byte 6 has 8 to 15, byte 7 has 16 to 23, byte 8 has 24 to 31).
The remaining 10 bits of time value are packed in Bytes 3 and byte 4 as follows:
byte 3 has 2 bits:32 and 33, and Byte 4 has remaining bits : 34 to 41.
So total bits for time value is 42 bits, packed as above.
I need to compute epoch value coming out of these 42 bits. How do I do it?
I have done something like this but not sure it gives me correct value:
typedef struct P_HEADER {
unsigned int tmuNumber : 22; //sorry for the typo.
unsigned int time1 : 10; // Bits 6,7 from Byte-3 + 8 bits from Byte-4
unsigned int time2 : 32; // 32 bits: Bytes 5,6,7,8
unsigned int traceKey : 32;
} __attribute__((__packed__)) P_HEADER;
Then in the code:
P_HEADER *header1;
//get input string in hexa,etc..etc..
//parse the input with the header as :
header1 = (P_HEADER *)inputBuf;
// then print the header1->time1, header1->time2 ....
long ttime = header1->time1|header1->time2;
Is this the way to get values out?
This will give you the value as you descibe it:
typedef struct P_HEADER {
unsigned int tmuNumber : 22;
unsigned int time1 : 10; // Bits 6,7 from Byte-3 + 8 bits from Byte-4
unsigned int time2 : 32; // 32 bits: Bytes 5,6,7,8
unsigned int traceKey : 32;
} __attribute__((__packed__)) P_HEADER;
long ttime = ((uint64_t)header1->time1) << 32 | header1->time2;
Works only like that on little-endian machines though.

Resources