2

Recently I encountered code that did this:

static_assert(sizeof(void*) >= sizeof(size_t));

size_t idx = get_index_to_array();
void* ptr = (void*)idx;

Essentially using a void* pointer provided by a third party library to store an index into an array to save an allocation.

Assuming that the pointer will neither be dereferenced nor freed/deleted at any point, and will be only used to cast back to the original value, is this code strictly conforming C++ (per the C++17 standard, if that matters)?

Dr. Gut
  • 2,053
  • 7
  • 26
0x400921FB54442D18
  • 725
  • 1
  • 5
  • 18
  • You might want to look at https://stackoverflow.com/questions/1845482/what-is-uintptr-t-data-type, which talks about `uintptr_t` – Marshall Clow Aug 31 '19 at 00:21
  • And, "Essentially using a void pointer provided by a third party" is fine, if it comes with guarantees. Does it? Aliasing? – Ted Lyngmo Aug 31 '19 at 00:22
  • @TedLyngmo 1) Do you have any evidence to support that claim? The fact that it "just works" on some compilers doesn't mean it's strictly conforming. 2) It's stated in the question that the pointer won't be manipulated in any other way than casting it back to size_t when needed. – 0x400921FB54442D18 Aug 31 '19 at 00:26
  • @0x400921FB54442D18 what exactly are you questioning? – Ted Lyngmo Aug 31 '19 at 00:28
  • 1
    What you *should* be asking is something like *"is there any benefit to doing this ?"* I sure can't think of any – Sid S Aug 31 '19 at 01:02
  • 2
    @SidS I can. Many C API's provide a function for registering callback to an event. Such callback will usually be given an option to pass user defined data in the form of a void pointer. If that data happens to be an integer, as a minor optimisation, you can avoid the indirection by reinterpreting the integer instead of passing a pointer to a separate object. – eerorika Aug 31 '19 at 01:25
  • @0x400921FB54442D18 When I say that using a `void*` provided by a third party is fine if it comes with guarantees I mean that the supplier of said pointer would have to make a promise. Such a promise is usually built on trust - a signed contract. The world of ASIL D certified components springs to mind. – Ted Lyngmo Aug 31 '19 at 07:27

2 Answers2

2

Asuming that the pointer will not get dereferenced nor freed/deleted at any point and will be only used to cast back to the original value, is this code strictly conforming C++ (per the C++17 standard, if that matters)?

It is conforming.

Since there is no compatible static cast, this explicit type conversion (colloquially called C-style cast) performs a reinterpret cast. Of this, the standard says (quoting the latest draft):

[expr.reinterpret.cast]

A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • There is something of a difference between “conforming” and “working” here—you might not get your integer back. – Davis Herring Aug 31 '19 at 02:31
1

If, as you say, this void* pointer will not be used for anything but being cast back to an int, then yes, this code is fine.

The C-style cast in (void*)idx falls back to a reinterpret_cast when all other casts fail (such as static_cast). Usually reinterpret cast is a dangerous thing, but it does come with the guarantee that casting to an intermediate type, then back to the original type, will always yield the original value. Thus, your code, under the stated constraints, is fine.

alter_igel
  • 6,899
  • 3
  • 21
  • 40