void*指针上的指针算术

Pointer arithmetic on void* pointers

本文关键字:指针 void      更新时间:2023-10-16

我正在使用CUDA API/cuFFT API。为了将数据从主机移动到GPU,我使用cudaMemcpy函数。我像下面这样使用它。len是dataReal和dataImag上的元素数量。

void foo(const double* dataReal, const double* dataImag, size_t len)
{
    cufftDoubleComplex* inputData;
    size_t allocSizeInput = sizeof(cufftDoubleComplex)*len;
    cudaError_t allocResult = cudaMalloc((void**)&inputData, allocSizeInput);
    if (allocResult != cudaSuccess) return;
    cudaError_t copyResult;
    coypResult = cudaMemcpy2D(static_cast<void*>(inputData),
                              2 * sizeof (double),
                              static_cast<const void*>(dataReal),
                              sizeof(double),
                              sizeof(double),
                              len,
                              cudaMemcpyHostToDevice);
    coypResult &= cudaMemcpy2D(static_cast<void*>(inputData) + sizeof(double),
                              2 * sizeof (double),
                              static_cast<const void*>(dataImag),
                              sizeof(double),
                              sizeof(double),
                              len,
                              cudaMemcpyHostToDevice);
    //and so on.
}

我知道,指针算术对void指针实际上是不可能的。第二个cudaMemcpy2D仍然工作。我仍然得到编译器的警告,但它工作正常。

我试过使用static_cast<但这不起作用,因为cuffDoubleComplex*不能静态转换为char*。>

我有点困惑,为什么第二个cudaMemcpy与指针算术在void上工作,因为我理解它不应该。编译器是否隐式地假设void*背后的数据类型是一个字节长?

我应该在那里做些改变吗?使用reinterpret_cast<例如,char*>(inputData) ?

同样在分配期间,我使用旧的c风格(void**)类型转换。我这样做是因为我得到了"从cufftDoubleComplex**到void**的无效static_cast"。有其他正确的方法吗?

仅供参考:链接到cudaMemcpy2D文档

链接到cudaMalloc文档

不能对void*进行算术运算,因为指针上的算术运算是基于指向对象的大小的(而sizeof(void)实际上没有任何意义)。

您的代码编译可能要感谢编译器扩展,将void*上的算术运算视为char*上的算术运算。

在您的情况下,您可能不需要算术运算,下面应该可以工作(并且更健壮):

coypResult &= cudaMemcpy2D(static_cast<void*>(&inputData->y),
                           sizeof (cufftDoubleComplex),

因为cufftDoubleComplex只是:

struct __device_builtin__ __builtin_align__(16) double2
{
    double x, y;
};