Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用仅在运行时初始化的函数指针解析[-Werror=可能未初始化]_C_Oop_Pointers - Fatal编程技术网

C 使用仅在运行时初始化的函数指针解析[-Werror=可能未初始化]

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

我正在用C11编写一段代码,希望能让我以后在程序中的生活更轻松。我想调用一个通用的
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
}