1

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?

Lundin
  • 195,001
  • 40
  • 254
  • 396

3 Answers3

3

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));
}
Rüppell's Vulture
  • 3,583
  • 7
  • 35
  • 49
  • Thank you! im not sure what the second statement is saying though? – RightLeftRight12 Apr 30 '13 at 06:03
  • Okay, so if i asked for just sizeof(p) it would just give me 4 because its a pointer right? – RightLeftRight12 Apr 30 '13 at 06:05
  • @user2127663 `sizeof(p)` would give you the size of the pointer, not the variable it points to.But in your program it could be confusing because in both cases it will be `4`.Had the size of your structure `tB` been say 8 bytes,then `sizeof(*p)` will give `8` but `sizeof(p)` will give 4.You understand now?Try it on your compiler. – Rüppell's Vulture Apr 30 '13 at 06:08
  • @user2127663 Try adding some more elements to your structure `tB` so that the size will be 5 or 6 bytes,then pass `sizeof(p)` and `sizeof(*p)` to `printf()` as arguments to see the difference. – Rüppell's Vulture Apr 30 '13 at 06:09
  • @user2127663 What do you want b1,b2,b3,b4 to be?Integers or characters?It's better to mention it. – Rüppell's Vulture Apr 30 '13 at 06:11
  • @user2127663 I am adding an altered version of your program to illustrate this difference. – Rüppell's Vulture Apr 30 '13 at 06:14
  • Wow thats all very helpful! I think ive grasped bit fields! Much Thanks – RightLeftRight12 Apr 30 '13 at 06:18
  • @user2127663 Listen here.You asked a VERY justified question `Why would I round to 32? Wouldn't 24 be the next one up? `.It rounds to 32 due to something called `padding`.Now `padding` is a whole different story so I won't elaborate on it.But I am adding another variation to your program that will kinda do away with the padding and round it to 24(or 3 bytes) as it is expected to. – Rüppell's Vulture Apr 30 '13 at 06:46
  • +1, a good answer , and as a side note i would like to mention that, code blocks is not a compiler, but an IDE which uses [mingw](http://www.mingw.org/) compiler, which is port of gcc on windows... – Barath Ravikumar Apr 30 '13 at 14:16
  • @BarathBushan I always wanted to know what's the difference between mingw,gcc and CodeBlocks.But never thought much of it due to time-constraints.Glad you told that in passing.I have some questions about other features of CodeBlocks like the Debugger.I hope you'll help me about that when I dig into that.OK?I am not sure it's allowed in StackOverflow to ask for other's email address. – Rüppell's Vulture Apr 30 '13 at 15:26
  • @SheerFish , For my work in C, i always used the gnu notepad, gcc compiler,gdb debugger,gnu makefiles and other tools/profilers only through the command line terminal on linux, and i hardly know a few details of codeblocks IDE and nothing more useful to be of any help....If you have any doubts regarding the usage of code blocks , then [codeblocks forum](http://forums.codeblocks.org/), is the place you would want to look at.....if you want to ask anybody on SO anything , then you can leave a message on [chat](http://chat.stackoverflow.com/users?tab=all&sort=name), instead of using the email. – Barath Ravikumar Apr 30 '13 at 16:31
1

You have 21 bits, round up to nearest int and you got 32 (i.e. 4 bytes).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Why would I round to 32? Wouldn't 24 be the next one up? – RightLeftRight12 Apr 30 '13 at 05:36
  • @user2127663 There are no 24-bit integer types. The ones you can choose from are `char` (8 bits), `short` (16 bits), `int` (32 bits), `long` (32 or 64 bits) and `long long` (64 bits). With bitfields, unless otherwise specified, it will always use `int` so always pad to the nearest 32-bit boundary. – Some programmer dude Apr 30 '13 at 05:38
  • Oh okay perfect that makes alot of sense! So if I was looking for b would it also be the same? – RightLeftRight12 Apr 30 '13 at 05:39
  • @user2127663 Yes it would. – Some programmer dude Apr 30 '13 at 05:40
  • @JoachimPileborg Won't risk/issues arise when we use something like `sizeof(*p)` where `p` hasn't been initialized and contains garbage value? – Rüppell's Vulture Apr 30 '13 at 05:59
  • @SheerFish `sizeof` is a compile-time operation, so no risk will be involved runtime. – Some programmer dude Apr 30 '13 at 05:59
  • @JoachimPileborg What is the default type of b when we use something like `unsigned b:4`, instead of `unsigned int b:4` or `unsigned char b:4`? – Rüppell's Vulture Apr 30 '13 at 06:17
  • There is no way you can tell what sizeof will yield as result here. There may be any number of padding bytes and bits in the struct, or there may be none. I know several platforms without alignment requirements, where the result would be 3 bytes. Even on a system with 32-bit alignment, the result could still be 3 bytes if the binary is compiled for optimal memory size, and then later in runtime temporarily expanded into 4 bytes when used in an expression. And then of course, there may be 64 bit systems giving the result 8 bytes. – Lundin Apr 30 '13 at 06:18
  • 1
    @Lundin In my platform the size of that struct variable `b` is being displayed as `4` even if I use only one bitfield of 3 bits.But it shows 1 as expected when when I use `#pragma pack(1)` ahead of the structure declaration to do away with the padding. – Rüppell's Vulture Apr 30 '13 at 06:22
  • @Lundin Can you tell me what I asked Joachim?What is the default type of b in `unsigned b:3`, if we use that instead of `unsigned int b:3` or `unsigned char b:3`? – Rüppell's Vulture Apr 30 '13 at 06:24
  • @Lundin Though I intuitively feel that it must be `int` – Rüppell's Vulture Apr 30 '13 at 06:25
  • 1
    @SheerFish Bit fields are very poorly defined by the standard. So there is generally no expected size from a bit field, since they are all relying on impl.defined behavior. Regarding the meaning of `unsigned`, that always means `unsigned int`, inside a bit field or not. In fact, unsigned/signed int is the only type you can safely use inside a bit field, the C standard does not cover any other type. If you want deterministic, portable code, you should not use bit fields. [Related post here.](http://stackoverflow.com/questions/6043483/why-bit-endianness-is-an-issue-in-bitfields/6044223#6044223) – Lundin Apr 30 '13 at 06:29
  • @Lundin Well,I favorited that post as it would need some time & effort to understand in entirety.Thanks. – Rüppell's Vulture Apr 30 '13 at 06:33
  • @JoachimPileborg Doesn't the size of bitfields round up to the nearly multiple of a byte instead of 1 byte for `char`,2 byte for `short` and 4 for `int`? – Rüppell's Vulture Apr 30 '13 at 06:43
  • @Lundin What is your take on my above comment?Doesn't the size of the bitfield or all the bitfields in a struct variable round to the nearest multiple of a byte? – Rüppell's Vulture Apr 30 '13 at 06:43
0

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.

mesmerizingr
  • 1,417
  • 1
  • 18
  • 25