c语言 - 在函数调用中自动将 void 指针转换为指向双精度的指针



我有一个问题,它可能已经在其他地方得到了回答,但我找不到它,所以如果它已经存在,我深表歉意。

我有以下代码:

#include <stdio.h>
void foo(double *number) {
printf("%fn", *number);
}
void bar(void *number) {
double *new_number = (double *)number;
printf("%fn", *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 编译器如何处理这些函数调用?

编译器知道如何转换指针。具体说来

  • 您的 C 编译器知道如何从double *转换为void *
  • 您的 C 编译器知道如何从已转换为void *double *转换回double *

(在您可能使用的计算机上,不需要实际转换。

它知道什么时候该做。具体说来

  • 当你投射到void *时,它知道它需要一个void *
  • 当你投射到double *时,它知道它需要一个double *
  • 当你分配给一个void *时,它知道它需要一个void *
  • 当你分配给一个double *时,它知道它需要一个double *
  • 当参数的类型为void *时,它知道它需要一个void *参数。
  • 当参数的类型为double *时,它知道它需要一个double *参数。

(你没有做所有这些,但我想包括一些常见的情况。

您的代码是一个很好的示例,说明如何使用void指针在函数之间传递任何类型的数据。

§6.3.2.3 指针 (C11 N1570)

  1. 指向void的指针可以转换为指向任何对象类型的指针,也可以从指向任何对象类型的指针相互转换。指向任何对象类型的指针都可以转换为指向void的指针,然后再返回;结果应与原始指针相等。

在幕后没有发生太多事情,编译器必须确保上述规则得到尊重。执行此操作的一种简单方法是使所有指针类型的大小相同。

重要的是,编译器还需要知道指针类型,以便执行通常的指针算术和运算。

首先,变量名称有点混乱(编辑前的标题也是如此)。通常,双指针被理解为指向指针的指针,而不是指向double的指针。

有人可能正在使用C++编译器来编译 C 代码。C++和C是不同的语言,有自己的规则。

在 C 语言中,您不需要从 或void *进行转换。在C++中,它需要一个显式强制转换,并且没有强制转换的代码将不会编译 https://godbolt.org/z/78KbW4Wdz

在后台,编译器只需要知道指针引用的数据类型。

对于初学者,您可以按以下方式更改功能栏

void bar(void *number) {
double *new_number = number;
printf("%fn", *new_number);
}

删除显式强制转换。

在 C 中,void * 类型的指针可以分配给指向任何其他类型的对象的指针。

所以在这个电话中

foo(test_void_pointer);
bar(test_double_pointer);

void * 类型的指针可以分配给双精度 * 类型的参数,反之亦然,双精度 * 类型的指针可以分配给 void * 类型的参数。

来自 C 标准(6.3.2.3 指针)

1 指向 void 的指针可以转换为指向任何 对象类型。指向任何对象类型的指针都可以转换为 指向 void 并再次返回的指针;结果应等于 原始指针。

相关内容

  • 没有找到相关文章

最新更新