C 使用仅在运行时初始化的函数指针解析[-Werror=可能未初始化]
我正在用C11编写一段代码,希望能让我以后在程序中的生活更轻松。我想调用一个通用的C 使用仅在运行时初始化的函数指针解析[-Werror=可能未初始化],c,oop,pointers,C,Oop,Pointers,我正在用C11编写一段代码,希望能让我以后在程序中的生活更轻松。我想调用一个通用的intersect函数。但是,根据某些情况,intersect函数实际上可能是不同的函数 请注意,intersect的第三个参数的指针类型取决于开关大小写,因此我不能真正概括它 同样的错误也出现在getnormal中 错误: error: ‘intersect’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 5
intersect
函数。但是,根据某些情况,intersect
函数实际上可能是不同的函数
请注意,intersect
的第三个参数的指针类型取决于开关大小写,因此我不能真正概括它
同样的错误也出现在getnormal
中
错误:
error: ‘intersect’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
57 | current_t = intersect(origin, direction, objects[i]);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
守则:
float inline iPlane(vec3 origin, vec3 direction, plane * pla);
float inline iTriangle(vec3 origin, vec3 direction, triangle * tri);
float inline iSphere(vec3 origin, vec3 direction, sphere * sph);
vec3 inline nTriangle(triangle * obj, vec3 position);
vec3 inline nPlane(plane * obj, vec3 position);
vec3 inline nSphere(sphere * obj, vec3 position);
float current_t;
vec3 (*getnormal)();
float (*intersect)();
object * nearest_obj = NULL;
for (int i = 0; i < object_count; ++i)
{
switch(objects[i]->shape){ // shape = enum{sphereobj, triangleobj, planeobj}
case triangleobj:
getnormal = &nTriangle; // real function that exists
intersect = &iTriangle; // also a real function that exists
break;
case sphereobj:
getnormal = &nSphere;
intersect = &iSphere;
break;
case planeobj:
getnormal = &nPlane;
intersect = &iPlane;
break;
}
current_t = intersect(origin, direction, objects[i]); // error here
}
浮动直列iPlane(vec3原点,vec3方向,平面*pla);
浮点内联iTriangle(vec3原点、vec3方向、三角形*tri);
浮点内联iSphere(vec3原点,vec3方向,球体*sph);
vec3内联nTriangle(三角形*obj,vec3位置);
vec3直列nPlane(平面*obj,vec3位置);
vec3内联nSphere(球体*obj,vec3位置);
浮动电流;
vec3(*getnormal)();
浮动(*相交)();
对象*最近的对象=空;
对于(int i=0;ishape){//shape=enum{sphereobj,triangleobj,planeobj}
案例三角形OBJ:
getnormal=&nTriangle;//存在的实函数
intersect=&iTriangle;//也是一个存在的实函数
打破
案例sphereobj:
getnormal=&nSphere;
intersect=&iSphere;
打破
案例B:
getnormal=&nPlane;
intersect=&iPlane;
打破
}
当前_t=相交(原点、方向、对象[i]);//此处出错
}
编译器无法保证对象[i]->shape
只是枚举中的一个值。从编译器的角度来看,objects[i]->shape
只是一个int
值
快速解决方案是添加一个default
案例,该案例使用一些合理的默认值
另一种解决方案是初始化指向
NULL
的指针,然后在使用它们之前进行检查。要消除警告,只需将函数指针变量初始化为0即可
float (*intersect)() = NULL;
然后在使用它之前,检查它是否已初始化(以防switch
语句中未包含所有枚举,在这种情况下会发出另一个警告,但安全性比抱歉要好)
或者不带assert(可以通过一些编译器开关消除)
如果情况可能发生:
我在C语言中发现了一个令人恼火的地方(或者它是gcc?),那就是如果shape字段是一个enum(例如在结构的定义中有一个显式的enum),那么编译器被告知shape将是给定值之一,您仍然需要输入默认值以避免出现警告。@dmuir这是因为在C中枚举值只是一种处理连续整数符号常量的好方法。在C规范中没有任何东西可以阻止一个人这样做,例如
objects[i]->shape=1234
。C++用范围枚举来解决它,但是它们的普通非范围枚举仍然非常接近C语义。
assert (intersect);
if (!intersect)
{
// handle the error
}
if (intersect)
{
current_t = intersect(origin, direction, objects[i]);
}
else
{
current_t = 0.0; // some default value else you get the "uninitialized error" with current_t
}