← Back to C Course | Chapter 12: Advanced Topics | Lesson 3 of 20

C Bit Fields

Bit fields let you squeeze several small values into one number by giving each a few bits, like sharing one page among many tiny notes. They save memory.
Syntax
c
struct StructName {
  unsigned int member_name : number_of_bits;
};

What are Bit Fields?

A bit field is a structure member declared with an explicit width in bits rather than a fixed built-in size, letting several small values share a single word of memory instead of each taking a whole int.

This is most useful for things like flag registers or protocol headers where memory is tight and every bit is accounted for.

Example: What are Bit Fields?

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Define a structure type named Flags
struct Flags {
	unsigned int status : 3;
};
// Program execution starts in main()
int main() {
	struct Flags f;
	f.status = 5;
	// Print formatted text to the screen
	printf("%d", f.status);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Defining Bit Fields

You declare a bit field by writing a colon followed by the number of bits directly after the member name inside a struct, for example unsigned status : 3; to reserve exactly 3 bits for status.

The compiler then packs that member alongside its neighbors instead of giving it a full byte or word.

Example: Defining Bit Fields

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Define a structure type named Flags
struct Flags {
	unsigned status : 3;
};
// Program execution starts in main()
int main() {
	struct Flags f;
	f.status = 6;
	// Print formatted text to the screen
	printf("%d", f.status);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Memory Packing Efficiency

A plain int member always costs 4 bytes regardless of the values it needs to hold, but a struct built from several small bit fields can pack many of those values into that same 4 bytes.

This matters when you have thousands of records in memory, since the packing can meaningfully cut total memory usage.

Example: Memory Packing Efficiency

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Define a structure type named Packed
struct Packed {
	unsigned a : 1;
	unsigned b : 1;
	unsigned c : 1;
};
// Program execution starts in main()
int main() {
	// Print formatted text to the screen
	printf("%zu", sizeof(struct Packed));
	// Return 0 to signal that the program finished successfully
	return 0;
}

Bit Field Value Limits

A bit field can only represent values that fit within the number of bits you gave it, so a 3-bit field can only hold 0 through 7 — assigning anything larger silently wraps around rather than raising an error.

Always size your bit fields to the actual range of values you expect to store.

Example: Bit Field Value Limits

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Define a structure type named Flags
struct Flags {
	unsigned value : 3;
};
// Program execution starts in main()
int main() {
	struct Flags f;
	f.value = 9;
	// Print formatted text to the screen
	printf("%d", f.value);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Unsigned Bit Fields

Signed bit fields are risky because one of the bits is reserved for the sign, and how that sign bit gets extended when the value is read back is implementation-defined across compilers.

Declaring bit fields as unsigned int avoids this ambiguity entirely and keeps the stored values behaving predictably.

Example: Unsigned Bit Fields

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Define a structure type named Flags
struct Flags {
	unsigned int status : 3;
};
// Program execution starts in main()
int main() {
	struct Flags f;
	f.status = 5;
	// Print formatted text to the screen
	printf("%u", f.status);
	// Return 0 to signal that the program finished successfully
	return 0;
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Taking the address of a bit field, which is not allowed.
  2. Storing a value larger than the bit field can hold.
  3. Assuming bit field layout is the same on every compiler.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.