繁体   English   中英

如何将结构指针类型转换为不同的指针以及如何在函数之间传递它?

[英]How to typecast structure pointer to different pointers and how to pass it between functions?

我有这些结构,顾名思义,它们保存圆形和矩形的数据。

typedef struct _circledata{
        FCOORD center;
        float radius;
        BOOL filled;
        COLORREF color;
        FCOORD *points;
}shapeCircle;

typedef struct _rectdata{
    FCOORD start;
    FCOORD end;
    FCOORD points;
    float length,breadth;
    BOOL filled;
    COLORREF color;
}shapeRect;

typedef enum {Circle, Rect, Triangle} objlist;

现在我有这段代码来检查鼠标指针是否悬停在圆形或矩形区域。 isMouseHovering() function 有 arguments; 指针 -> 是圆形还是矩形,枚举 -> 形状枚举数

//In WinMain I initialize two circles 
    shapeCircle newCirc[2];
//gave them values

for(int i=0;i<2;i++){
  if(isMouseHovering( //have to send pointer to struct and enum value ){
              //I tried like this 
              //if(isMouseHovering((void*)newCirc+i,Circle))
     newCirc[i].color=red;
     newCirc[i].radius=55;
     //Do stuffs
  }else{
     //Do something else
  }

在 isMouseHovering() 我有这种类型的代码,

BOOL isMouseHovering(void *obj,int objnum){  //I did like this and tried to typecast the pointer
    int val=0;

    switch(objnum){      //diverting the checking code based on shape type
        case Circle:
            return checkCircleHover( (shapeCircle*) obj ); //sending the pointer of struct
            break;
        case Rect:
            /* * * * */
            break;
        case Triangle:
            /* * * * */
            break;
        default: 
            /* * * * */
            return -1;
    }
    return 0;
}

所以你可以看到我到底想要实现什么。 我需要将任何结构指针发送到一个 function,然后它将检查形状并将其传输到正确的 function。 我知道我的方法是错误的,因为它不起作用。 那么这些方法是否有任何解决方法。

谢谢你。

萨米1410

您的isMouseHovering() function 没有什么特别的问题。 如果您实际提供的任何代码都存在或暗示错误,则它位于对该 function 的注释掉调用中:

 //if(isMouseHovering((void*)newCirc+i,Circle))

与所有一元运算符一样,类型转换运算符的优先级高于+ ,因此表达式(void*)newCirc+i等价于((void*)newCirc)+i 但是您不能对指向void的指针执行指针运算。 如果您的编译器无论如何都接受了,那么它很可能会像指针是char *一样执行算术,在这种情况下这将是一场灾难。 如果您没有收到该代码的警告,请调高编译器的警告级别。

部分问题是您正在执行不需要的演员表。 Object 指针会自动转换为void *类型和跨赋值类型,并作为 function arguments,所以尽管您可以将上述调用编写为...

              // ok
              isMouseHovering((void*)(newCirc + i), Circle)

...最好完全省略演员表:

              // better
              isMouseHovering(newCirc + i, Circle)

同样,在isMouseHovering()中,您不需要将void *强制转换为特定于形状的函数所接受的特定指针类型。 我也会省略那个演员表,因为除了算术目的之外的演员表有不好的代码味道。 然而,那至少有一些文献价值。


话虽如此,我认为您可能会发现需要在每次调用时指定 object 类型充其量是不方便的。 如果您总是使用指向特定形状类型的指针,那么您可以用通用选择宏替换您的isMouseHovering() function:

#define isMouseHovering(s) _Generic((s), \
    shapeCircle*:   checkCircleHover(s), \
    shapeRect*:     checkRectHover(s), \
    shapeTriangle*: checkTriangleHover(s),
    default:        -1)

这将产生适合指针类型的 function 调用,而不需要鉴别器值,但是当然,如果指针类型没有(正确)传达指向 object 的类型,则它不会按预期工作,例如您已转换为类型void *


另一方面,我预计您可能会发现需要编写接受混合形状的函数,或者您希望在到达基于特定形状类型进行区分之前通过多层 function 调用传递形状指针. 为此,您有两个相当不错的选择:

  1. 创建一个包含形状类型代码和指向特定形状的指针的包装结构。 @zakk's answer 对此进行了更全面的描述,我觉得没有必要添加任何内容。 或者

  2. 创建一个可以表示任何形状的标记联合类型。 这将涉及通过添加类型代码作为第一个成员来稍微修改您的形状结构以适应。 例子:

     typedef enum {Circle, Rect, Triangle} objlist; typedef struct _circledata{ objlist type; FCOORD center; float radius; //... } shapeCircle; typedef struct _rectdata{ objlist type; //... } shapeRect; typedef struct _triangledata{ objlist type; //... } shapeTriangle; typedef union { struct { objlist type; }; shapeCircle asCircle; shapeRect asRect; shapeTriangle asTriangle; } anyShape;

    然后,您主要使用anyShape类型的对象和/或指向该类型的指针,顾名思义,它可以表示任何形状。 当您需要具体了解特定实例代表何种形状时,无论当时它代表何种形状,object 中的信息都在那里。

您可以为所有形状定义一个enum

enum ShapeType {SHAPE_CIRCLE, SHAPE_RECTANGLE, SHAPE_TRIANGLE}; // You can add more

然后,定义一个具有类型以及指向您的形状的指针的通用结构:

struct shape {
    enum ShapeType shape_type;
    void *object;
};

现在,无需为isMouseHovering()提供第二个参数:

BOOL isMouseHovering(void *obj)
{
    struct shape *shape = obj;

    switch(shape->shape_type) {
        case SHAPE_CIRCLE:
            return checkCircleHover((shapeCircle*)shape->object);
            break;
        case SHAPE_RECTANGLE:
            /* * * * */
            break;
        case SHAPE_TRIANGLE:
            /* * * * */
            break;
        default: 
            /* * * * */
            return -1;
    }
    return 0;
}

你的checkCircleHover()将接受一个shapeCircle* ,因为如果你调用它,你确定你正在向它传递一个圆圈:

BOOL checkCircleHover(shapeCircle *circle)
{
    // ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM