10

So, what exactly is "*const ()" in Rust? It seems I can "as" some primitive value (integer value, function) to this type in Rust like the code shown below:

let foo = 1;
let pointer = foo as *const ();  // this works.

But for floating-point numbers and so on, the compiler doesn't allow us to do the above coercion, so what is "*const ()" in Rust? Is it similar to void* in C/C++? If so, why doesn't it support pointing to floating-point numbers?

BTW, adding the case where this pattern is currently used in the Reference: https://doc.rust-lang.org/std/mem/fn.transmute.html.

fn foo() -> i32 {
    0
}
let pointer = foo as *const ();  // here it is!!!
let function = unsafe {
    std::mem::transmute::<*const (), fn() -> i32>(pointer)
};
assert_eq!(function(), 0);
Boann
  • 48,794
  • 16
  • 117
  • 146
Jason Yu
  • 1,886
  • 16
  • 26
  • @eggyal This is not what I am looking for. My curiosity is about the "raw pointer to a unit value" since the unit value is somewhat useless and trivial in Rust, so I want to know what kind of scenarios we can use this pattern. – Jason Yu Apr 13 '21 at 14:42
  • @eggyal I see, it's a little bit weird about why floats can't. – Jason Yu Apr 13 '21 at 15:06
  • Why? Memory addresses are integers. What memory address would `3.141 as *const ()` represent? – eggyal Apr 13 '21 at 15:11
  • @eggyal, You are right, sorry, confused with the reference cast. Here we are using the value itself. – Jason Yu Apr 13 '21 at 15:14

2 Answers2

9

*const () is very similar to C's const* void indeed, except for the fact that () represents exactly one value, while void represents no values. Relevant answer about difference between () and void

If so, why doesn't it support pointing to the floating-point numbers?

It does, it's just that foo as *const () has nothing to do with pointing to a float, it has to do with taking a value and converting it to a pointer with the same numeric value, which doesn't make sense for floats.

Ivan C
  • 1,772
  • 1
  • 8
  • 13
  • 1
    I think this is a bit misleading because `(const) void*` is not _really_ a pointer to a `void`; it's a [very special case](https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_void). So the difference between `void` and `()` doesn't tell you the difference between `const void*` and `*const ()`. – Alexey Romanov Apr 13 '21 at 18:31
3

The example just uses *const () as an arbitrary non-function pointer type, as it says:

Turning a pointer into a function pointer.

It would be exactly the same for an *const i32 or other types, but the authors needed to pick one and () is the simplest.

Is it similar to the void* in C/C++?

Not really. It's a pointer to (), which is a perfectly ordinary type (if zero-sized), and doesn't have special rules like void* does. See also

A Rust curiosity: pointers to zero-sized types

Final conclusion: arithmetic on a void* is illegal in both C and C++ (where arithmetic using .offset on a *const () is perfectly fine).

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487