CSS Prepare

optional · CSS study notes

II.15 Structures, Unions, and Bit Manipulation

⬆️ P-I.II. Programming Fundamentals · Question Bank · Chapter II (2016–2026)

🧠

Remember: Struct stores together; union shares; masks select bits.

Start here — what you should be able to do

  • Design records and pass them to functions.
  • Explain union storage and active members accurately.
  • Calculate bitwise results and use valid masks.

Reading order: foundation checks → full notes and examples → exam traps → self-test without notes → past-paper answers. All sections below remain part of the topic; code examples are kept in full.

Foundation checks

Bit-mask toolkit

Use an unsigned value x and an unsigned mask 1u << k, with k within the type's bit width.

OperationExpression
Set bit`x
Clear bitx &= ~mask
Toggle bitx ^= mask
Test bit(x & mask) != 0
Power of twox != 0 && (x & (x - 1)) == 0

Memory: ordinary struct members have separate storage, with possible padding. A union has shared storage sufficient for its largest member plus alignment requirements. Active member: do not assume reading arbitrary inactive union members is portable C++. Enum: unassigned enumerators start at zero and then increment; an explicit value changes the subsequent sequence.

1. Structures (struct)

  • Groups different data types under one name; each member gets its own separate memory, so the struct's total size is (at least) the sum of its members' sizes
struct Student {
    char name[20];
    int age;
    float gpa;
};
struct Student s1 = {"Ali", 20, 3.8};
printf("%s", s1.name);       // dot operator to access members
  • Members are accessed with the dot operator (.) on a struct variable, or the arrow operator (->) via a pointer to a struct: ptr->name
  • Nested structures: a struct can contain another struct as a member
  • Structures can be passed to functions by value (a full copy) or by reference/pointer (to avoid copying and/or allow modification)

2. Unions

  • Union: members share storage; size is sufficient for the largest member and alignment requirements, not the sum.
union Data {
    int i;
    float f;
    char c;
};
union Data d;
d.i = 10;     // writing to i overwrites the same memory f and c would use
  • Useful when only one of several possible types is needed at a time (memory-saving), e.g. representing a value that could be an int OR a float depending on context
  • Active member: ordinary C++ union use has one active member; arbitrary inactive-member reads are not portable type-punning.

3. Struct vs Union

structunion
Memory per memberSeparate for eachShared (overlapping)
Total sizeOrdinary members plus any paddingSufficient for largest member and alignment
Simultaneous accessAll members valid at onceOnly the most recently written member is valid

4. Enumerations (enum)

  • A user-defined type consisting of a set of named integer constants, improving readability over "magic numbers"
enum Day {SUN, MON, TUE, WED, THU, FRI, SAT};   // SUN=0, MON=1, ... by default
enum Day today = WED;   // today holds the integer value 3

5. Bit Manipulation Operators

OperatorNameEffect
&AND1 only if both bits are 1
OR
^XOR1 if bits differ
~NOTFlips every bit (1's complement)
<<Left shiftShifts bits left; each shift multiplies by 2
>>Right shiftShifts bits right; each shift divides by 2 (for unsigned/positive values)
  • Example: 6 & 3 → 0110 & 0011 = 0010 = 2; 6 | 3 → 0110 | 0011 = 0111 = 7; 6 ^ 3 → 0101 = 5
  • 5 << 1 = 10 (multiply by 2); 5 >> 1 = 2 (divide by 2, truncated)

6. Bit Masking / Flags Technique

  • A common low-level pattern for storing multiple boolean flags compactly in one integer:
#define READ  1   // 001
#define WRITE 2   // 010
#define EXEC  4   // 100
int perms = READ | WRITE;      // set flags: 011
if (perms & WRITE) { ... }      // check a flag: is WRITE set?
perms = perms & ~WRITE;         // clear a flag: unset WRITE
  • Used in permission systems, hardware registers, and status flags where memory efficiency matters

7. 💻 Code Examples: C & C++

Struct, union, enum, and a bit-flag permissions example, all in one program:

C:

#include <stdio.h>
struct Student { char name[20]; int age; float gpa; };
union Data { int i; float f; };
enum Day { SUN, MON, TUE, WED, THU, FRI, SAT };

#define READ  1   // 001
#define WRITE 2   // 010

int main(void) {
    struct Student s1 = {"Ali", 20, 3.8};
    printf("%s is %d, GPA %.1f\n", s1.name, s1.age, s1.gpa);  // dot operator

    union Data d;
    d.i = 10;
- **Size example:** the union's size accommodates its largest member and alignment; int/float are often four bytes, but check the actual implementation.

    enum Day today = WED;
    printf("today = %d\n", today);            // 3

    int perms = READ | WRITE;                   // set flags: 011
    if (perms & WRITE) printf("write allowed\n");  // check a flag
    perms = perms & ~WRITE;                       // clear a flag
    return 0;
}

C++:

#include <iostream>
using namespace std;
struct Student { string name; int age; float gpa; };  // C++ allows std::string as a member
union Data { int i; float f; };
enum Day { SUN, MON, TUE, WED, THU, FRI, SAT };

const int READ  = 1;  // 001
const int WRITE = 2;  // 010

int main() {
    Student s1{"Ali", 20, 3.8f};               // C++11 brace initialization
    cout << s1.name << " is " << s1.age << ", GPA " << s1.gpa << endl;

    Data d;
    d.i = 10;
    cout << "d.i=" << d.i << " (sizeof union = " << sizeof(d) << ")" << endl;

    Day today = WED;
    cout << "today = " << today << endl;         // 3

    int perms = READ | WRITE;
    if (perms & WRITE) cout << "write allowed" << endl;
    perms = perms & ~WRITE;
    return 0;
}
  • Size example: the union's size accommodates its largest member and alignment; int/float are often four bytes, but check the actual implementation.

8. MCQ Traps

  • In a struct, each member has separate memory; in a union, all members share the same memory
  • Union size: at least enough for the largest member, with alignment/padding as required.
  • Accessing a struct member via a pointer requires the arrow operator (->), not the dot operator
  • enum values default to 0, 1, 2, ... in declaration order unless explicitly assigned otherwise
  • Left shift (<<) multiplies by 2 per shift; right shift (>>) divides by 2 per shift — but only under the appropriate unsigned/range and valid-shift-count conditions

9. Self-Test Questions — with answers

Q1. Why is union storage based on the largest member?

Answer

  • Members overlap the same storage.
  • It must be sufficient for the largest member and satisfy alignment requirements; it is not the sum of member sizes.
  • Ordinary C++ use has one active member at a time.

Q2. Which operator accesses a member through a pointer?

Answer

  • ptr->member, equivalent to (*ptr).member.
  • Use object.member when you have the struct object itself.

Q3. Compute 12 AND 10, OR 10 and XOR 10.

Answer

  • 12 = 1100; 10 = 1010.
  • AND: 1000 = 8.
  • OR: 1110 = 14.
  • XOR: 0110 = 6.

Q4. What values do JAN, FEB and MAR have by default?

Answer

  • For enum Month { JAN, FEB, MAR };: 0, 1 and 2.
  • If JAN is explicitly 1, the following unassigned values become 2 and 3.

Q5. How do OR and AND set and test a flag?

Answer

  • Set: flags |= mask.
  • Test: (flags & mask) != 0.
  • Clear: flags &= ~mask.
  • Use an unsigned mask and a valid bit position.
  1. Why does a union's size equal its largest member's size rather than the sum of all members?
  2. What operator is used to access a struct member through a pointer, and why?
  3. Compute 12 & 10, 12 | 10, and 12 ^ 10 in binary.
  4. What integer values do the enum constants {JAN, FEB, MAR} take by default?
  5. Describe how bitwise OR and AND can be used to set and check a flag bit, respectively.

10. 📝 Exam Practice: Binary Logic Gate Simulator

Q: Write a C/C++ program which implements binary logical 'AND', 'OR', and 'XOR' gates. The program takes binary numbers and a desired logical gate, and outputs the result of the gate.

Solution:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string bin1, bin2, gate;

    cout << "Enter first binary number: ";
    cin >> bin1;

    cout << "Enter second binary number: ";
    cin >> bin2;

    cout << "Enter desired gate (AND / OR / XOR): ";
    cin >> gate;

    // Pad the shorter string with leading zeros so both are equal length
    int maxLen = (bin1.length() > bin2.length()) ? bin1.length() : bin2.length();
    while (bin1.length() < maxLen) bin1 = "0" + bin1;
    while (bin2.length() < maxLen) bin2 = "0" + bin2;

    string result = "";
    for (int i = 0; i < maxLen; i++)
    {
        int bit1 = bin1[i] - '0';   // convert char '0'/'1' to int 0/1
        int bit2 = bin2[i] - '0';
        int resBit;

        if (gate == "AND" || gate == "and")      resBit = bit1 & bit2;
        else if (gate == "OR" || gate == "or")   resBit = bit1 | bit2;
        else if (gate == "XOR" || gate == "xor") resBit = bit1 ^ bit2;
        else { cout << "Invalid gate entered."; return 0; }

        result += (resBit == 1) ? '1' : '0';
    }

    cout << "\nResult of " << gate << " operation: " << result << endl;
    return 0;
}

Sample run:

Enter first binary number: 1010
Enter second binary number: 1100
Enter desired gate (AND / OR / XOR): AND

Result of AND operation: 1000

Column-method trace (matches the textbook's "evaluate by column" approach):

Positionbin1bin2ANDORXOR
111110
201011
310011
400000

Key reasoning points:

  • Binary numbers are treated as strings, not integers — each character is processed individually with &, |, ^ applied to single 0/1 ints, mirroring the textbook's column-by-column method
  • Shorter input is zero-padded on the left first, so both operands align at the same bit positions
  • Matches the chapter's summary rules exactly: AND needs both bits 1, OR needs at least one bit 1, XOR needs an odd count of 1 bits (here just "the two bits differ")

11. 📜 Past-Paper Questions & MCQs (CSS 2016–2026)

2016 · Paper-I · Q4(a) · 6 marks

Recall cue: Define the record fields; input the complete record; test age boundaries; display the category.

Q. Define a structure for a Person (name, age, address). Input one record and display "Young" if age < 20, "Old" if age > 50, otherwise "Middle".

Answer — key points

struct Person { char name[30]; int age; char address[50]; };
int main() {
    Person p;
    cout << "Enter Name = ";    cin.getline(p.name, 30);
    cout << "Enter Age = ";     cin >> p.age;  cin.ignore();
    cout << "Enter Address = "; cin.getline(p.address, 50);
    if (p.age < 20)      cout << "Person is YOUNG";
    else if (p.age > 50) cout << "Person is OLD";
    else                 cout << "Person is MIDDLE";
}
  • The paper leaves ages 20 and 50 undefined, so treat them as Middle.

2017 · Paper-I · Q3(c) · 6 marks

Recall cue: Store code, name and price together; find the code; multiply price by quantity; accumulate the bill.

Q. Write a supermarket checkout program. The database of items (name, code, price) is a structure. The cashier enters codes and quantities, and the program prints the total.

Answer — key points

struct Item { int code; char name[20]; float price; };
Item db[3] = { {1,"Rice",500}, {2,"Sugar",150}, {3,"Oil",400} };
float total = 0; char more;
do {
    int code, qty;
    cout << "Enter product code: ";  cin >> code;
    cout << "Enter quantity: ";      cin >> qty;
    for (int i = 0; i < 3; i++)
        if (db[i].code == code) total += db[i].price * qty;
    cout << "Do you have more products to add (Y/N): "; cin >> more;
} while (more == 'Y' || more == 'y');
cout << "The total amount is " << total;
  • To search by name, compare with strcmp(db[i].name, input) == 0.

2019 · Paper-I · Q5(b) · 5 marks and 2023 · Paper-I · Q3(c) · 6 marks

Recall cue: Define bitwise operations; demonstrate masks; use unsigned values and valid shift counts.

Q. What is bit twiddling? Give a brief description.

Answer — key points

  • Bit twiddling (bit manipulation) means working directly on the individual bits of data using bitwise operators &, |, ^, ~, <<, >>.
  • Why: it is fast and memory-efficient, so it is used in device drivers, graphics, cryptography, compression and flags.
  • Examples:
    • odd or even: n & 1
    • multiply by 2: n << 1
    • set bit k: n | (1 << k)
    • clear bit k: n & ~(1 << k)
    • toggle bit k: n ^ (1 << k)
    • power of two test: n != 0 && (n & (n - 1)) == 0
    • swap without a temporary: a ^= b; b ^= a; a ^= b;

2022 · Paper-I · Q4(b) · 8 marks

Recall cue: Write both numbers in binary; OR each bit; convert 11101 back to 29.

Q. Write the output of the program with a = 12, b = 25 that prints a | b.

Answer — key points

  • 12 = 01100, 25 = 11001, so 12 | 25 = 11101 = 29.
  • Output:
a = 12
b = 25
a | b = 29

2025 · Paper-I · Q4(c) · 8 marks

Recall cue: Represent real and imaginary parts; add corresponding fields; format negative imaginary parts correctly.

Q. Demonstrate two complex numbers using a structure. Use a function to add them and display the result as (a + bi).

Answer — key points

struct Complex { float re, im; };
Complex add(Complex x, Complex y) { return { x.re + y.re, x.im + y.im }; }
void show(Complex c) {
    cout << "(" << c.re << (c.im < 0 ? " - " : " + ") << (c.im < 0 ? -c.im : c.im) << "i)";
}
int main() {
    Complex a, b;
    cout << "First (real imag): ";  cin >> a.re >> a.im;
    cout << "Second (real imag): "; cin >> b.re >> b.im;
    show(add(a, b));
}

2026 · Paper-I · Q3(a) · 6 marks

Recall cue: Explain bit manipulation; show checking and setting/clearing bits; avoid blanket performance claims.

Q. What is bit manipulation in programming, and why is it used? Give two examples.

Answer — key points

  • Bit manipulation uses bitwise operators (&, |, ^, ~, <<, >>) to read or change individual bits.
  • Why used: speed, low memory use, and direct control of flags, masks, hardware registers, compression and encryption.
  • Example 1: checking odd or even with n & 1 (1 means odd).
  • Example 2: setting and clearing a bit with flags |= (1 << 3) and flags &= ~(1 << 3).

MCQs

2026 P-I · Q3. A programmer wants to group different data types. What should he or she use?

  • (A) Structures ✅
  • (B) Arrays
  • (C) Unions
  • (D) None of these
  • Answer: (A) Structures.
  • Why: a structure holds members of different types together, each with its own memory (for example an int, a float and a char array). An array holds elements of one type only. A union also mixes types, but all members share the same memory, so only one value is valid at a time.

Technical accuracy notes

  • For unsigned n, a power-of-two test must exclude zero: n != 0 && (n & (n - 1)) == 0.
  • Use unsigned masks such as 1u << k, with k less than the type's bit width. Bitwise operations are not automatically faster than arithmetic after optimisation.
  • A union is large enough for its largest member and obeys alignment requirements. Its members share storage, but arbitrary access through an inactive member is not portable C++ type-punning. C++ working draft.
  • Prefer a temporary variable or an appropriate swap function over XOR swapping, particularly when two expressions may alias.

Recall check and coverage

  • Explain the three learning outcomes at the top without looking.
  • Reproduce one example or trace and test a boundary case.
  • Answer each self-test, then compare with the key.
  • Attempt each recorded past-paper task on this page.
  • Recorded written references: 2016 · Paper-I · Q4(a) · 6 marks; 2017 · Paper-I · Q3(c) · 6 marks; 2019 · Paper-I · Q5(b) · 5 marks and 2023 · Paper-I · Q3(c) · 6 marks; 2022 · Paper-I · Q4(b) · 8 marks; 2025 · Paper-I · Q4(c) · 8 marks; 2026 · Paper-I · Q3(a) · 6 marks

Evidence limit: this page preserves the question records found in your Notion notes. Disputed labels and questions not checked against original PDFs remain flagged in the Question Bank; this is not a claim of exhaustive original-paper verification.