我一直在通过不同的编译器运行以下代码:
int main()
{
float **a;
void **b;
b = a;
}
从我已经能够收集,void **
是不是一个普通的指针,这意味着从另一个指针任何转换不应该编译或至少抛出一个警告。但是,这是我的结果(全部在Windows上完成):
- gcc-如预期的那样发出警告。
- g ++ -引发错误,如预期的那样(这是由于C ++的宽松输入造成的,对吧?)
- MSVC(cl.exe) -即使指定了/ Wall,也不会引发任何警告。
我的问题是:我是否遗漏了全部内容?是否有任何特定原因导致MSVC无法发出警告?MSVC 做转换时产生警告从 void **
到float **
。
还要注意的另一件事:如果我将其替换a = b
为显式转换a = (void **)b
,则所有编译器都不会发出警告。我认为这应该是无效的演员表,所以为什么不会有任何警告?
我问这个问题的原因是因为我开始学习CUDA并在官方编程指南(https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-memory)中学习可以找到以下代码:
// Allocate vectors in device memory
float* d_A;
cudaMalloc(&d_A, size);
应该执行对void **
for 的隐式转换&d_A
,因为的第一个参数cudaMalloc
是类型void **
。在整个文档中都可以找到类似的代码。这只是NVIDIA的草率工作,还是我又错过了什么?由于nvcc
使用MSVC,因此代码编译时不会发出警告。
void**
不是通用指针。只有void*
。
(void**)
是显式的c样式强制转换。它告诉编译器不要仔细观察您的工作并信任您。它是对类型安全系统的显式覆盖,并且要求编译器基本上接受任何类型的转换。应该避免C样式转换,因为它们太强大了。使用C ++强制转换,例如static_cast
,如果您尝试做没有意义的操作,将会抱怨。