Pointer cast to a plain integral type

ID

objectivec.correctness.pointer_to_integral_cast

Severity

low

Remediation Complexity

hard

Remediation Risk

medium

Remediation Effort

medium

Resource

Cast

Language

Objective-C

Description

Reports a cast of a value that is certainly a pointer - self, _cmd, an address-of expression, or the result of a cast to a pointer type - to a plain C integral type such as int, long or size_t. uintptr_t, intptr_t, NSInteger and NSUInteger, the types defined to hold a pointer, are not reported.

Rationale

Nothing in the language says a pointer fits in the integer it is being squeezed into. Where it does not, the address is truncated silently: the cast compiles, the arithmetic looks right, and the value only becomes wrong for allocations above the type’s range - which is why this survives testing on one architecture and fails on the next. int is the sharp case, since it stays 32 bits on the 64-bit runtime where every object address is 64. Even where the widths happen to agree, the result of the conversion is implementation-defined rather than portable, and casting the integer back to a pointer is only guaranteed to round-trip through the types intended for it.

The following code illustrates the pattern detected by this rule:

@implementation Registry
- (void)tagEntries {
    // FLAGGED: Pointer cast to a plain integral type
    long identity = (long)self;
    // FLAGGED: Pointer cast to a plain integral type
    int truncatedIdentity = (int)self;
    // FLAGGED: Pointer cast to a plain integral type
    size_t selectorTag = (size_t)_cmd;
    // FLAGGED: Pointer cast to a plain integral type
    long backingAddress = (long)&_backing;
    // FLAGGED: Pointer cast to a plain integral type
    unsigned int bufferTag = (unsigned int)(char *)self.bytes;
    NSLog(@"%ld %d %zu %ld %u", identity, truncatedIdentity, selectorTag, backingAddress, bufferTag);
}
@end

Remediation

Use uintptr_t (or intptr_t) from <stdint.h> when an address genuinely has to be held as an integer - both are defined to round-trip through a pointer without loss. On Apple platforms NSUInteger serves the same purpose and reads more naturally in Objective-C, which is why -hash returning (NSUInteger)self is idiomatic. Better still, ask whether the integer is needed at all: an NSValue wrapping the pointer, or an NSMapTable keyed by object identity, keeps the pointer a pointer.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved