0

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?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
scoder
  • 3
  • 5
  • Is there a question here? Bitfields are laid out in some implementation defined way with implementation defined padding, leading to implementation defined sizes of the containing structures. All you can say for certain is that `s1` requires at least 13 bits and `s2` requires at least 3. – Chris Dodd Aug 06 '17 at 13:54
  • 1
    The value `-6` doesn't fit into a 3-bit bit-field. Also, there's nothing that says that any of the fields in `struct marks` is signed — plain `int` in a bit-field may be signed or unsigned. Almost everything about bit-fields is implementation-defined. Since you don't even mention 'bit-field' in your question, it is puzzling — are you sure you know about them? They're weird, and generally not worth bothering with. They're a source of endless questions on SO, but I don't recall needing to use one in over 30 years of coding in C — but not much device-level coding, where they can be useful. – Jonathan Leffler Aug 06 '17 at 14:08
  • [to print sizeof uses `%zu`, not `%lu`](https://stackoverflow.com/q/940087/995714) – phuclv Aug 06 '17 at 14:56
  • I recall needing to use bit-fields last week, and it's good that C/C++ have them. For instance, bit-fields are useful in image processing. I'm using bit-fields to store WebP LZ77 codes in a compact way, so I won't run into memory problems with very large images. Actually, bit-fields are just a very nice shorthand notation for shift/and operations. – SBS Aug 06 '17 at 19:11

2 Answers2

5

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.

  • why isn't it that if the memory requirement is 13 bits overall for s1, then it could have packed the size to 2 bytes as it has 16 bits which can accomodate 13 bits. Anyways the extra 2 bytes are not useful right? – scoder Aug 06 '17 at 14:08
  • @scoder it's never less than the size of the type you're using. –  Aug 06 '17 at 14:10
  • @scoder: Because it is up to the implementation to decide what to do, and because you used the type `int` instead of `short`. Had you used `short` for the bit-fields, if your compiler allowed that (it isn't obliged to), then it might have used a 2-byte storage unit. There is almost nothing legislated about the behaviour of bit-fields — it is almost all implementation defined. – Jonathan Leffler Aug 06 '17 at 14:10
  • As @Jonathan Leffler wrote: bitfields are used nowadays mostly in the embedded programming. The behaviour is implementation defined - usually used with compiler specific attributes or pragmas - but portability is not something what bare metal coders care too much, as the code will almost never compiled using another compiler. – 0___________ Aug 06 '17 at 14:24
  • @Jonathan so you mean, the least size would be taken into account within which all the bits can fit in, and in this case, it is only int hence it is 4 bytes? – scoder Aug 06 '17 at 14:34
  • 1
    @scoder: compilers are allowed to do more or less what they like as long as they document it. Many compilers allocate a 'storage unit' for contiguous bit-fields based on the size of the type specified as the base type for the bit-fields. If you work on a system with 32-bit `int`, then the compiler is certainly allowed to allocate a 32-bit unit for one or more bit-fields declared with the type `int` — and many compilers do that. But the standard probably doesn't insist on that (it doesn't insist on much w.r.t bit-fields, except that they shall be supported, and it rules out some gross abuse). – Jonathan Leffler Aug 06 '17 at 14:42
-1

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.

Robert Andrzejuk
  • 5,076
  • 2
  • 22
  • 31