I am a bit confused with the output of the following code although I know what the declaration of such struct means in C.
#include<stdio.h>
struct struc
{
int a:1;
int b:3;
int c:6;
int d:3;
}s1;
struct stru
{
char a:3;
}s2;
int main()
{
printf("%lu %lu",sizeof(s1),sizeof(s2));
getchar();
return 0;
}
I am trying to learn the actual working of this type of structure declaration.
Can anyone explain how the code is giving output as "4 1", as I want to get the grasp over the concept properly.
And also the following code:
#include <stdio.h>
struct marks{
int p:3;
int c:3;
int m:2;
};
int main(void) {
struct marks s={2,-6,5};
printf("%d %d %d",s.p,s.c,s.m);
return 0;
}
What should be the output from this program?
The code you show is using bit fields. In a nutshell, :n after a struct member restricts this member to use only n bits, and such members are "packed" together when adjacent members have the same type.
A long time ago, this was sometimes useful to save memory -- nowadays, you might need it in very low-level hardware interfacing code, but that's probably about it.
What happens here:
struct struc
{
int a:1;
int b:3;
int c:6;
int d:3;
}s1;
This struct only has 1 + 3 + 6 + 3 = 13 bits worth of information. Assuming your implementation uses 32 bit int and a char has 8 bits, the sizeof int is 4 (32 / 8), and this is still enough to store all the bits of your members here. So the size of the whole struct is still only 4.
Note that all of this is implementation defined -- it depends on the sizes of char and int and the compiler is still free to add padding as needed. So using bitfields requires you to know what exactly your implementation is doing, at least if you need to rely on sizes and the exact layout of the bits.
In the example we can see that the 1st struct uses int and the 2nd struct uses a char.
The char gives a size result of 1. Which I think is as expected.
If we look at the sizes of variables :
cpp reference - types
Then we can see that an int can take up 16 or 32 bits.
As size of your struct is 4 we can determine that your compiler uses 32 bits for this storage.
Related
I was trying to find the answer of a question which involves two structures inside a union.
I have typed the question in online debugger the answer which I am finding and the real answer is not giving hands to each other. Can somebody help me out with the answer with explanation.
#include <stdio.h>
int main()
{
union{
struct{
char c[2];
char ch[2];
}s;
struct {
short int i;
short int j;
}st;
}u={12,1,15,1};
printf("%d%d",u.st.i,u.st.j);
}
answer is 268 and 271
Decimal numbers are not very good for this kind of tests. You should also enable all warnings as well. If you do so you will get
<source>:25:8: warning: missing braces around initializer [-Wmissing-braces]
So let's rewrite your program a little bit:
int main()
{
union
{
struct
{
char c[2];
char ch[2];
}s;
struct
{
short int i;
short int j;
}st;
}u={.s = {{0x12,0x01},{0x15,0x01}}}; //better to show compiler what you want to initialize
printf("%04hx %04hx",u.st.i,u.st.j);
}
And the result is:
0112 0115
clearly showing the numbers we have used in the initialization. The numbers show us that this system uses little endian system where the least significant byte is placed first.
You should be avare that compiler is free to add any padding needed. To avoid it you have to use compiler extensions - structure packing.
Start by making more sense of this by swapping to hexadecimal: {0xC,0x1,0xF,0x1}. This allows us to view the bytes as they are stored in memory, without worrying about converting to/from decimal base.
When initializing a union, the first member gets initialized, in this case the struct s.
It would be cleaner to write { {{0xC,0x1}, {0xF,0x1}} } but unfortunately C allows omitting the curly braces of inner structs/arrays, allowing us to put sloppily written crap in our initialization lists just because we can.
The memory order of a char byte array is always top to bottom on any system: first byte on least significant address. That is: 0xC 0x1 0xF 0x1.
Strictly speaking, the compiler is free to add struct padding bytes anywhere between the struct/union members, to compensate for misalignment. Doesn't happen in this specific case, but it would happen if we for example used char c[3].
When you "type pun" this memory area using shorts, they get read according to endianess, since short is larger than 1 byte and an integer type.
On a little endian CPU you would therefore get each short to assume that 0xC is the least significant byte and so the first short ends up as 010C hex.
If we translate your code to hex, it should be clearer:
#include <stdio.h>
int main()
{
union{
struct{
char c[2];
char ch[2];
}s;
struct {
short int i;
short int j;
}st;
}u={ {{0xC,0x1}, {0xF,0x1}} };
printf("%.4X\n%.4X",u.st.i,u.st.j);
}
Output on little endian CPU:
010C
010F
10Ch = 268d and so on.
My question is we do padding to align structures.
typedef struct structb_tag
{
char c;
int i;
} structb_t;
Here we use 8 bytes. Why can't we use the 3 bytes that lot?
Why cant we use the 3 bytes
You could.
To do so measure the size your implementation allocates for a struct and then make it a union adding a char-array of exactly the size measured and there you go.
Assuming this
typedef struct structb_tag
{
char c;
int i;
} structb_t;
is created using eight bytes, that is sizeof (structb_t) evaluates to 8, change it to the following
typedef union unionb_tag
{
char bytes[8];
struct
{
char c;
int i;
} structb;
}
More reliable, in terms of portability and also robustness, would be this:
typedef union unionb_tag
{
struct structb_tag
{
char c;
int i;
} structb;
char bytes[sizeof (struct structb_tag)];
}
If you are using GCC and space is the most important thing for you instead of speed (which padding provides) you could just request the compiler to not do the padding, struct __attribute__((__packed__)) mystruct, padding is the way for compiler to align structures in the natural for faster access.
You can always take the pointer to the structure convert it to a byte pointer and access any byte of that structure.This is dangerous way, though.
The padding are implementation dependent, which are not defined by the standard, you cannot not use them as there is no way to reference the padding bytes.
Yes, you can.
typedef struct structb_tag
{
char c;
char pad[3];
int i;
} structb_t;
structb_t test;
test.pad[0] = 'a';
In short, we can use that three bytes.
The reason why we need 3 bytes padding is for memory usage optimization, so the compiler will help us add an gap between c and i. So when you use
typedef struct structb_tag
{
char c;
int i;
} structb_t;
It actually
typedef struct structb_tag
{
char c;
char[3] unseen_members;
int i;
} structb_t;
Accessing these unseen members will not cause any segmentation fault. In the point of view of OS, there's no difference between accessing members declared by programmers explicitly and declared by compiler implicitly.
#include <stdio.h>
#include <string.h>
typedef struct Test {
char c;
int i;
} MyTest;
int main() {
MyTest my_test;
memset(&my_test, 0, sizeof(my_test));
my_test.c = 1;
int* int_ptr = (int *)&my_test.c;
printf("Size of my_test is %lu\n", sizeof(my_test));
printf("Value of my_test.c(char) is %d\n", my_test.c);
printf("Value of my_test.c(int) is %d\n", *int_ptr);
return 0;
}
This gives:
Size of my_test is 8
Value of my_test.c(char) is 1
Value of my_test.c(int) is 1
We can access any byte in the structure using a pointer to that structure and typecasting that pointer to (char *) if we accordingly increment that pointer then we can access any byte but this not good programming skill. Structures are padded with some extra bytes so that an execution of the program can become faster.
I was going through this question to reaffirm my understanding of structure padding.I have a doubt now. When I do something like this:
#include <stdio.h>
#define ALIGNTHIS 16 //16,Not necessarily
union myunion
{
struct mystruct
{
char a;
int b;
} myst;
char DS4Alignment[ALIGNTHIS];
};
//Main Routine
int main(void)
{
union myunion WannaPad;
printf("Union's size: %d\n\
Struct's size: %d\n", sizeof(WannaPad),
sizeof(WannaPad.myst));
return 0;
}
Output:
Union's size: 16
Struct's size: 8
should I not expect the struct to have been padded by 8 bytes? If I explicitly pad eight bytes to the structure, the whole purpose of nesting it inside an union like this is nullified.
I feel that declaring a union containing a struct and a character array the size of the struct ought to be but isn't, makes way for a neater code.
Is there a work-around for making it work as I would like it?
Think about it logically.
Imagine I had a union with some basic types in it:
union my_union{
int i;
long l;
double d;
float f;
};
would you expect sizeof(int) == sizeof(double)?
The inner types will always be their size, but the union will always be large enough to hold any of its inner types.
should I not expect the struct to have been padded by 8 bytes?
No, as the struct mystruct is seen/handled on its own. The char had been padded by 3 sizeof (int) -1 bytes to let the int be properly aligned. This does not change, even if someone, somewhere, sometimes decides to use this very struct mystruct inside another type.
By default struct is padded, so int b field is aligned on sizeof(int) boundary. There are several workarounds for this:
explicitly use fillers where needed: char a; char _a[sizeof(int)-1]; int b;
use compiler-dependent pragma to pack struct on byte boundary
use command-line switch etc.
I tried to use bit fields in a struct for some values which only need one or two bits instead of a whole byte.
My code is:
struct s_rdata {
signed int p0:28;
signed int p1:28;
signed int p2:28;
unsigned int d0:17;
unsigned int d1:17;
unsigned int d2:17;
unsigned char data1:1;
unsigned char data2:1;
} rdata;
So, you might see that there are variables named p0 - p2, d0 - d2 and data1 - data2.
I'd now like to have those in an array. However, none of this lines does work:
signed int p[3]:28;
signed int p:28[3];
Can't I add an array to a bitfield list, an array of signed int only needing 28 bits per entry?
No, you cannot have an array of bitfields, nor a bitfield whose base type is an array type. The latter doesn't even make sense. The former would be counter-productive, as you would lose any space efficiency gained by using bitfields in the first place.
You can have an array of a structs with a single bitfield member:
struct container {
signed int bitfield:7;
} array[3];
but again, you would lose any space efficiency associated with the bitfield use.
You can create an array of any struct type, of course, including those with multiple bitfield members. In that case, you may achieve some internal space efficiency within the individual structures, but you will likely see padding at the end of each one that reduces the overall space efficiency of the array.
Ultimately, unless your program's memory consumption is excessive for its target environment, I strongly recommend that you forget about bitfields. They will complicate your life for an uncertain gain of uncertain importance, and that gain will likely be offset by a performance degradation (of uncertain magnitude and importance).
Should you eventually decide that the program really is using too much memory, then be certain to test any change you make to see how much improvement it yields, and at what cost.
I agree with #John's assessment with respect to space inefficiencies, but that notwithstanding, here is an idea to contain contents of a bit field within struct array:
typedef struct
{
int A : 16;
int B : 16;
} Struct1;
typedef struct
{
Struct1 B;//bitfield struct
int array[10];//combined with array (of any legal type)
}
Here is an example of populating array with contents of bit struct:
typedef struct {
signed int p0:28;
signed int p1:28;
signed int p2:28;
unsigned int d0:17;
unsigned int d1:17;
unsigned int d2:17;
unsigned char data1:1;
unsigned char data2:1;
} RDATA;
typedef struct {
int A[3];
unsigned int B[3];
unsigned char C[2];
} ARRAY;
RDATA rdata = {//initialize instance of RDATA with data
28,
28,
28,
17,
17,
17,
1,
1
};
int WriteToArray(ARRAY *a);
int main(void)
{
ARRAY a;
WriteToArray(&a);//populate array with RDATA values
//ARRAY is now populated with bitfield values;
a.A[0];
a.A[1];
//and so on
return 0;
}
WriteToArray(ARRAY *a)
{
a->A[0]=rdata.p0;//using values initialized above
a->A[1]=rdata.p1;
a->A[2]=rdata.p2;
a->B[0]=rdata.d0;
a->B[1]=rdata.d1;
a->B[2]=rdata.d2;
a->C[0]=rdata.data1;
a->C[1]=rdata.data2;
return 0;
}
You can also experiment with pragma pack statements to look at effects on space, but refer to #John's comment under your post for additional considerations regarding pragma and spacing.
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.