Bit-field declared in a struct or union

ID

objectivec.maintainability.avoid_bit_fields

Severity

info

Remediation Complexity

medium

Remediation Risk

medium

Remediation Effort

medium

Resource

Type Safety

Language

Objective-C

Description

Reports a bit-field declaration - a member declared with a width, as in unsigned int enabled : 1 - including the anonymous padding form unsigned int : 4. A signed bit-field of width one is not reported here; the signed-bit-field rule owns that case, so the two rules never report the same member. A case or default label, a keyword argument in a message send, a ternary, and occurrences inside a block comment are not reported.

Rationale

Almost everything about a bit-field is left to the implementation: whether the bits are allocated from the low or the high end of the storage unit, whether a field may straddle a unit boundary, how much padding the compiler inserts, and - for a plain int field - whether the field is even signed. That makes the memory layout unportable, so a struct of bit-fields cannot be relied on to describe a hardware register or a wire format, which is usually why it was written. A bit-field also has no address, so it cannot be passed by pointer, and concurrent writes to two different fields of the same storage unit are a data race even though the fields are distinct.

The following code illustrates the pattern detected by this rule:

struct DeviceFlags {
    // FLAGGED: Bit-field declared in a struct or union
    unsigned int enabled : 1;
    // FLAGGED: Bit-field declared in a struct or union
    unsigned int mode : 3;
    // FLAGGED: Bit-field declared in a struct or union
    uint8_t retries : 4;
    // FLAGGED: Bit-field declared in a struct or union
    unsigned int : 4;
    // FLAGGED: Bit-field declared in a struct or union
    signed int span : 3;
    signed int direction : 1;
    int polarity : 1;
    int8_t marker : 1;
    NSInteger mark : 1;
    // FLAGGED: Bit-field declared in a struct or union
    BOOL ready : 1;
    // FLAGGED: Bit-field declared in a struct or union
    NSUInteger counter : 1;
    BOOL plain;
    uint8_t tally;
};

Remediation

Where the members are independent flags, declare them as separate BOOL members and let the compiler choose the layout. Where the packing genuinely matters, hold a single integer of a fixed-width type and define named masks and shift accessors for each field, so the layout is written in the source rather than chosen by the compiler; an NS_OPTIONS enum is the idiomatic Objective-C form of that.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved