Pointers and integer types

Jens Gustedt, INRIA, France

org: ISO/IEC JCT1/SC22/WG14 document: N2822
target: IS 9899:2023, TS 6010:2023 version: 0
date: 2021-9-19 license: CC BY

Introduction

The current C standard has the types [u]intptr_t optional, because at the time it was designed mapping pointer representations onto integer types was a challenge. This situation has much changed over time. Processor architectures with pointer or integer instructions that operate on a number of bits that is not a power of 2 or that present standard integer types with padding are rare. In a search for such architectures we recently only found two platforms that still take advantage of the option not to define [u]intptr_t. Both are platforms with 128 bit pointer types that seem to be stuck in the intmax_t ABI trap, which is 64 bit wide for them.

Therefore we think that it is time to do our users a service and to harden C’s integer and pointer model such that the [u]intptr_t types aliases become mandatory. This does not mean that we introduce a flat address space nor that pointer arithmetic can generally be reduced to arithmetic in uintptr_t.

A second advantage of being able to rely on uintptr_t is the possibility to make the specifications in the memory model TS 6010 simpler and comprehensible. By the proposed change it will be possible to identify the abstract address that corresponds to a pointer value and the uintptr_t value to which it is converted.

Changes

Change in 7.20.1.4 (Integer types capable of holding object pointers) p1, last sentence

These types are optionalrequired.

NOTE: The types intptr_t and uintptr_t are possibly wider than the types intmax_t and uintmax_t (7.20.1.5). This exception is intended to accommodate implementations that otherwise would not be able to specify intptr_t and uintptr_t consistent with the rules for these types.

Rationale:

Not having these types is an inpediment for portability and for more comprehensive and portable memory and pointer model for C and in particular for TS 6010.

We have only found two architectures that do not provide these types. Both have pointers with a width of 128 bit, but seem not to have a standard or extended integer type that would fit to that. Since 128 bit integer types will be more and more demanded by the market (Rust e.g requires them) these implementations will have to provide them at some point in the future, anyhow. Public domain implementations that coerce two 64 bit integers in one 128 bit integer are publicly available and widely tested. Since we exempt these types from coverage by intmax_t and uintmax_t, see below, there are no implications for C library interfaces.

Change in 7.20.1.5 (Greatest-width integer types) p1

The following type designates a signed integer type capable of representing any value of any signed integer type with the possible exception of an extended integer type that is referred by the type definition for intptr_t:

intmax_t

The following type designates the unsigned integer type capable of representing any value of any unsigned integer type that corresponds to intmax_tFNT2:

uintmax_t

These types are required.

FNT2 Thus this type is capable of representing any value of any unsigned integer type with the possible exception of an extended integer type that is referred by the type definition for uintptr_t.

Rationale:

Adding intptr_t and uintptr_t or wide extended integer types of a width of 128 or 256 could be in conflict with existing ABI for intmax_t and uintmax_t. Therefore we create this minor exception such that those implementations will be able to add such an integer type as extended integer type and still be conforming.

Questions to WG14

  1. Shall we integrate Changes 2.1 and 2.2 into C23?

  2. Shall we integrate Changes 2.1 and 2.2 into TS 6010?