[英]Is it safe to pass a void pointer to function that accepts a non-void pointer?
很简单,以下代码是安全/可移植的吗?
#include <stdio.h>
#include <stdlib.h>
int add(int *a, int *b)
{
return *a + *b;
}
int main()
{
int x = 2;
int y = 3;
void *ptr1 = &x;
void *ptr2 = &y;
fprintf(stdout, "%d + %d = %d\n", x, y, add(ptr1, ptr2));
return EXIT_SUCCESS;
}
我用-Wall -Werror
和-Wextra
编译了这个并没有收到任何警告; 它似乎运行良好。
这是安全的:
指向void的指针可以转换为指向任何不完整或对象类型的指针。 指向任何不完整或对象类型的指针可能会转换为指向void的指针并再次返回; 结果应该等于原始指针。
但是你需要确保你的原始指针类型是正确的。
有两件事需要考虑:
C允许从void指针到任何其他对象指针类型的隐式转换。 因此,传递这些参数在语法上是可以的。
指向的实际对象的类型以及函数所需的指针类型必须满足严格的别名约束,否则您的程序处于未定义的行为域。
两点都没关系。 所以你的程序非常好。
这很好但是你的牙齿皮肤。
您正在将int*
转换为void*
并且当指针通过值传递给add
,它将转换回int*
。
例如,如果add
两个指针来double
,那么代码的行为将是未定义的。
它是“安全的”,因为行为定义明确。 当一个函数被声明为接受void *
时,它需要处理许多不同类型的数据是正常的; 例如memcpy
。
这在道德上并不安全。 通过传递void *
您使编译器无法检查您传递的指针是否指向包含您期望的形式和数量的数据的内存。 然后由您来强制执行此操作。
在你琐碎的例子中,你可以看到对象实际上是int
,一切都很好。
但是,一般情况下,在我们将void *
传递给函数的情况下,我们还应该传递额外的信息来描述我们正在移交的内存,其中详细说明函数可以完成其工作; 如果我们有一个只能处理一种类型的函数,那么我们会对设计决策进行长期而艰苦的研究,这些决策使我们传递的是void *
值而不是那种类型。
为了理智(并且,取决于编译器,性能),请考虑将您未编写的参数标记为const
。
如果你知道你转换为void *的指针总是属于一组已知的类型(例如char,short,int等),你可以创建一个由一个联合和一个判别式组成的结构类型,并传递给它相反,必要时重新铸造。
您可以将其作为指向未定义类型的指针传递,只是为了比void *更具体,并且以这种方式承担一些责任。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.