很简单,以下代码是安全/可移植的吗?
#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
对此进行了编译,但没有收到任何警告;它似乎运行正常。
答案 0 :(得分:4)
安全:
指向void的指针可以转换为指向任何不完整或对象类型的指针。指向任何不完整或对象类型的指针可能会转换为指向void的指针并再次返回;结果应该等于原始指针。
但是你需要确保你的原始指针类型是正确的。
答案 1 :(得分:4)
需要考虑两件事:
C允许从void指针到任何其他对象指针类型的隐式转换。因此,在语法上可以传递这些论点。
指向的实际对象的类型以及函数所需的指针类型必须满足strict aliasing约束,否则您的程序处于未定义的行为区域。
两点都没关系。所以你的程序非常好。
答案 2 :(得分:2)
这很好但是靠你的牙齿。
您正在将int*
转换为void*
,当指针按值传递到int*
时,会转换回add
。
例如,如果add
指向double
两个指针,那么代码的行为将是未定义的。
答案 3 :(得分:0)
这是“安全的”,因为行为定义明确。当需要处理许多不同类型的数据时,将函数声明为接受void *
是正常的;例如memcpy
。
道德安全。通过传递void *
,您使编译器无法检查您传递的指针是否指向包含您期望的形式和数量的数据的内存。然后由您来强制执行此操作。
在你琐碎的例子中,你可以看到对象实际上是int
,一切都很好。
然而,一般情况下,在我们将void *
传递给函数的情况下,我们还应该传递额外的信息来描述我们正在移交的内存,其中详细说明函数可以完成其工作;如果我们有一个只能处理一种类型的函数,那么我们会对设计决策进行长期而艰苦的研究,这些决策使我们传递void *
值而非该类型。
为了理智(并且,取决于编译器,性能),请考虑将您未写入的参数标记为const
。
答案 4 :(得分:0)
如果你知道你转换为void *的指针总是属于一组已知的类型(例如char,short,int等),你可以创建一个由一个联合和一个判别式组成的结构类型,并通过它,如有必要,重新铸造。
你可以将它作为指向未定义类型的指针传递,只是为了比void *更具体,并且以这种方式承担一些责任。