1

Does the C standard require pointers to be (integer) numbers?

One may argue that yes, because of pointer arithmetic...

But on the other hand operations like -- or ++ may be understood as previous memory location, next memory location, depending on how they are described in the standard, and actual implementation may use any representation to hold pointer data (as long as mentioned operations are implemented)...

Another question comes to mind - does C require arrays/buffers etc. to be contiguous, i.e. next element is stored in next memory location (++p where p is a pointer)? I ask because you can often see implementations online that seem to assume that it does.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
zduny
  • 2,481
  • 1
  • 27
  • 49
  • Pointers are not integers but are processed as numeric values. For example how are you going to represent a machine address?! – Vlad from Moscow Dec 25 '19 at 14:15
  • The C standard uses the term *abstract machine*. The actual implementation is relevant only to the (hardware) implementors. – wildplasser Dec 25 '19 at 14:15
  • @VladfromMoscow Well, for example: one could imagine a machine that addresses memory cells the same way we address our homes. It would be dumb, but possible. – zduny Dec 25 '19 at 14:18
  • See this answer https://stackoverflow.com/a/15151542/817643 – StoryTeller - Unslander Monica Dec 25 '19 at 14:19
  • @mrpyo it is not the address is the reference which can be anything. – 0___________ Dec 25 '19 at 14:19
  • 1
    *"does C require arrays/buffers etc. to be contiguous"* Yes, *"An array type describes a contiguously allocated nonempty set of objects..."* (C11) – HolyBlackCat Dec 25 '19 at 14:24
  • Your argument that pointers should be integral is flawed. Yes, pointers support a lot of arithmetic operations that integral types do. But, if you look at the arithmetic operations supported by pointers, a lot of them are also supported by floating point types. There are operations supported by pointers (e.g. dereferencing) that are supported by neither integral nor floating point types. – Peter Dec 25 '19 at 14:30
  • @VladfromMoscow: Other ways of addressing memory other than a simple numbering of bytes include segment and offset, word addressing (where the words are addressed by hardware and the C implementation has to manufacture addresses for bytes, which may result in `int *` and `char *` having different representations), pointers with additional information in them (such as data for security checks), pointers that do not point directly to main memory but to a data structure with information about loading necessary data from disk, bank-switched memory, and more. – Eric Postpischil Dec 25 '19 at 14:35
  • @EricPostpischil In any case addresses are stored as numeric values whether there is a flat memory or a segmented memory. – Vlad from Moscow Dec 25 '19 at 15:36
  • @VladfromMoscow If you want to be pedantic, as bit-patterns which can be interpreted among others as a number, and probably three different "natural" ways, floating-point, signed and unsigned. Whether that reinterpretation is natural depends on the pointer-format. – Deduplicator Dec 25 '19 at 23:44

2 Answers2

3

No, pointers need not be plain numbers.

If you read the standard, there are provisions for that:

  1. Two pointers to unrelated objects (meaning not part of a bigger object, remember structs and arrays) may not be compared, except for equality.

    6.5.8 Relational operators

    [...]
    5 When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object or incomplete types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P. In all other cases, the behavior is undefined.

  2. Two pointers to unrelated objects may not be subtracted.

    6.5.6 Additive operators

    [...]
    9 When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the twoarray elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header. If the result is not representable in an object of that type, the behavior is undefined. In other words, if the expressions P and Q point to, respectively,the i-th and j-th elements of an array object, the expression (P)-(Q) has the value i−j provided the value fits in an object of type ptrdiff_t. Moreover, if the expression P points either to an element of an array object or one past the last element of an array object, and the expression Q points to the last element of the same array object, the expression ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value zero if the expression P points one past the last element of the array object, even though the expression (Q)+1 does not point to an element of the array object.91)

  3. There may not be a way to represent a pointer as a number, as no suitable type might exist. Thus, trying to convert might result in Undefined Behavior.

    Any specific implementation defining a behavior does not mean it isn't UB according to the standard.

    6.3.2.3 Pointers

    [...]
    6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of anyinteger type.

    7.18.1.4 Integer types capable of holding object pointers

    1 The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

    intptr_t
    

    The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

    uintptr_t
    

    These types are optional.

That's just off the top of my head, I'm sure there's more.

All quotes from n1256 (C99 draft).

Arrays have always been required to be contiguous.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
0

To answer to your second question in arrays elements are in contiguous Memory locations. Thats why you use pointer arithmetic to move between elements.

Math Lover
  • 148
  • 10