我有一个问题,它可能已经在其他地方得到了回答,但我找不到它,所以如果它已经存在,我深表歉意。
我有以下代码:
#include <stdio.h>
void foo(double *number) {
printf("%f\n", *number);
}
void bar(void *number) {
double *new_number = (double *)number;
printf("%f\n", *new_number);
}
int main()
{
double test_number = 3.0;
double *test_double_pointer = &test_number;
void *test_void_pointer = (void *)test_double_pointer;
foo(test_double_pointer);
foo(test_void_pointer);
bar(test_double_pointer);
bar(test_void_pointer);
return 0;
}
结果是
3.000000
3.000000
3.000000
3.000000
我不明白引擎盖下发生了什么。 C 编译器如何处理这些函数调用?
C 编译器如何处理这些函数调用?
你的编译器知道如何转换指针。具体来说,
double *
转换为 void *
.double *
的 void *
转换回 double *
。(在您可能使用的机器上,不需要实际转换。)
它知道什么时候去做。具体来说,
void *
时,它知道它需要一个void *
。double *
时,它知道它需要一个double *
。void *
时,它知道它需要一个void *
。double *
时,它知道它需要一个double *
。void *
时,它知道它需要一个void *
参数。double *
时,它知道它需要一个double *
参数。(你不会做所有这些,但我想包括一些常见的情况。)
您的代码很好地说明了如何使用
void
指针在函数之间传递任何类型的数据。
- 指向
的指针可以转换为指向任何对象类型的指针或从指向任何对象类型的指针转换。指向任何对象类型的指针都可以转换为指向void
的指针,然后再转换回来;结果应与原始指针比较。void
幕后发生的事情并不多,编译器必须确保遵守上述规则。一个简单的方法是让所有指针类型的大小相同。
首先,变量名称有点混乱(编辑前的标题也是如此)。通常,双指针理解为指向指针的指针,而不是指向
double
的指针。
有人可能正在使用 C++ 编译器来编译 C 代码。 C++ 和 C 是不同的语言,有自己的规则。
在 C 语言中,您不需要从
void *
进行转换。在 C++ 中,它需要显式转换,没有转换的代码将无法编译https://godbolt.org/z/78KbW4Wdz
在幕后,编译器只需要知道指针引用的数据类型。
对于初学者,您可以按以下方式更改功能栏
void bar(void *number) {
double *new_number = number;
printf("%f\n", *new_number);
}
删除显式转换。
在 C 中,类型 void * 的指针可以分配给指向任何其他类型的对象的指针。
所以在这个电话中
foo(test_void_pointer);
bar(test_double_pointer);
void * 类型的指针可以分配给 double * 类型的参数,反之亦然,double * 类型的指针可以分配给 void * 类型的参数。
来自C标准(6.3.2.3指针)
1 指向 void 的指针可以转换为或从指向任何指针的指针转换 对象类型。指向任何对象类型的指针都可以转换为 指向 void 并再次返回的指针;结果应比较等于 原始指针。