C 与 C++,void** 指针的处理
C vs. C++, handling of void** pointers
我发现使用 C 编译器可以运行下面的代码,但不能使用 C++ 编译器。我知道强制转换为 void**
是正确的用法,但我不明白为什么即使我使用 void*
(已注释掉)它也会使用 C 编译器进行编译。
#include <stdio.h>
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
int main()
{
int value = 99;
int *pvalue = &value;
// fn((void *)&pvalue); // works only in C
// error C2664: 'int fn(void **)': cannot convert argument 1 from 'void *' to 'void **'
fn((void **)&pvalue); // correct, works for both C/C++
printf("%d", value);
return 0;
}
有人可以解释为什么会这样吗?
I can't understand why it compiles with the C compiler even if I use the void* (commented out).
它编译是因为 void*
可以隐式转换为 C 中的其他指针。
fn((void **)&pvalue); // correct, works for both C/C++
由于强制转换,这可能是格式正确的,该标准在技术上并未明确保证转换为 void**
并返回相同的地址。
虽然这在实践中可能会奏效,但没有理由不使用 void*
作为函数参数,这确实有保证。作为奖励,您不需要在通话中进行演员表。像这样:
int fn(void *arg);
fn(&pvalue); // correct, works for both C/C++
当然,这是假设首先需要类型擦除。不需要时避免void*
。
在 C 中,允许将 void *
类型的指针分配给其他类型的指针。这发生在这个调用
fn((void *)&pvalue)
其中参数的类型为 void *
,分配给函数参数的类型为 void **
。
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
但是这样的赋值通常是不安全的。例如,类型为 void * 的指针的值无法正确对齐以分配给其他类型的指针。
所以决定在C++中不允许这样的赋值,让程序更安全。
为免生疑问,
中没有任何正确的地方
fn((void **)&pvalue);
它和
一样不正确
fn((void *)&pvalue);
API的正确使用方法是
int fn(void **arg)
{
int *pvalue = (int *)*arg;
*(int *)pvalue = 200;
return 0;
}
或
int fn(void **arg)
{
*(int *)*arg = 200;
return 0;
}
和
int main()
{
int value = 99;
void *pvalue = (void*)&value;
fn(&pvalue);
printf("%d", value);
return 0;
}
您不能使用除声明类型、兼容类型或字符类型之外的任何其他指针类型访问对象。此外,虽然 void *
在 C 中用作指向各种对象的通用指针类型,但在 C 中没有指向指针类型的通用指针 - 除了 void *
!
这就是为什么 void **
几乎总是 API 中设计错误的标志 - 大多数用法都是错误的。
我发现使用 C 编译器可以运行下面的代码,但不能使用 C++ 编译器。我知道强制转换为 void**
是正确的用法,但我不明白为什么即使我使用 void*
(已注释掉)它也会使用 C 编译器进行编译。
#include <stdio.h>
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
int main()
{
int value = 99;
int *pvalue = &value;
// fn((void *)&pvalue); // works only in C
// error C2664: 'int fn(void **)': cannot convert argument 1 from 'void *' to 'void **'
fn((void **)&pvalue); // correct, works for both C/C++
printf("%d", value);
return 0;
}
有人可以解释为什么会这样吗?
I can't understand why it compiles with the C compiler even if I use the void* (commented out).
它编译是因为 void*
可以隐式转换为 C 中的其他指针。
fn((void **)&pvalue); // correct, works for both C/C++
由于强制转换,这可能是格式正确的,该标准在技术上并未明确保证转换为 void**
并返回相同的地址。
虽然这在实践中可能会奏效,但没有理由不使用 void*
作为函数参数,这确实有保证。作为奖励,您不需要在通话中进行演员表。像这样:
int fn(void *arg);
fn(&pvalue); // correct, works for both C/C++
当然,这是假设首先需要类型擦除。不需要时避免void*
。
在 C 中,允许将 void *
类型的指针分配给其他类型的指针。这发生在这个调用
fn((void *)&pvalue)
其中参数的类型为 void *
,分配给函数参数的类型为 void **
。
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
但是这样的赋值通常是不安全的。例如,类型为 void * 的指针的值无法正确对齐以分配给其他类型的指针。
所以决定在C++中不允许这样的赋值,让程序更安全。
为免生疑问,
中没有任何正确的地方fn((void **)&pvalue);
它和
一样不正确fn((void *)&pvalue);
API的正确使用方法是
int fn(void **arg)
{
int *pvalue = (int *)*arg;
*(int *)pvalue = 200;
return 0;
}
或
int fn(void **arg)
{
*(int *)*arg = 200;
return 0;
}
和
int main()
{
int value = 99;
void *pvalue = (void*)&value;
fn(&pvalue);
printf("%d", value);
return 0;
}
您不能使用除声明类型、兼容类型或字符类型之外的任何其他指针类型访问对象。此外,虽然 void *
在 C 中用作指向各种对象的通用指针类型,但在 C 中没有指向指针类型的通用指针 - 除了 void *
!
这就是为什么 void **
几乎总是 API 中设计错误的标志 - 大多数用法都是错误的。