Because of the broken CUDA API, the correct answer is to write a wrapper around their trash:
void* saneMalloc (size_t n)
{
void* tmp;
if (cudaMalloc(&tmp, n) == cudaSuccess)
return tmp;
return NULL;
}
...
float* a = saneMalloc(n);
You have to do this because the only generic pointer type in C is void*. You can convert from any pointer-to-type to void*, but that does not apply to void**. So if you have a float, you cannot pass on float** to a function expecting a void**. This is an incompatible pointer type.
Specifically, when passing parameters to function, they are copied as per the rules of simple assignment (C17 6.5.16.1). Passing a float** to a function expecting a void** is a constraint violation of the simple assignment rule. The code is not allowed to compile cleanly, as it is a C standard violation.