这个代码定义得很好(Casting HANDLE)

时间:2011-07-25 18:42:05

标签: c

在我最近工作的代码库中有许多与此类似的代码实例。这是围绕OS API的瘦C包装器。

// From the OS
HANDLE CreateObject();
void CloseHandle(HANDLE);

typedef struct tagFOO {} FOO;

FOO* Foo_New()
{
    return (FOO*)CreateObject();
}

void Foo_Delete(FOO* foo)
{
    if(foo != NULL)
    {
        CloseHandle((HANDLE)foo);
    }
}

void Foo_Bar(FOO* foo)
{
    if(foo != NULL)
    {
        HANDLE h = (HANDLE)foo;
        // Do something interesting with h
    }
}

这似乎有效,如果可以,我想避免接触它,但是这个定义得很好吗?这对我来说似乎非常可疑

3 个答案:

答案 0 :(得分:2)

HANDLE定义的意图是一个不透明的类型,你无法做出任何假设。在实践中,我们知道它是一个指针,并且由于Windows具有向后兼容性,因此不太可能发生变化。

这确实有巨大的代码味道,如果你有一半的借口我会重构它。但是,如果你不管它,我认为你不会冒很大的风险。

答案 1 :(得分:2)

C99标准说:

  

6.7.2.1结构和联合说明符

     

语法

struct-or-union-specifier:
       struct-or-union identifieropt { struct-declaration-list }
       struct-or-union identifier
struct-or-union:
       struct
       union
struct-declaration-list:
       struct-declaration
       struct-declaration-list struct-declaration

正式地说,这排除了你的空结构定义(C89标准中的§6.5.2.1也是如此);结构中至少应有一个成员。但是,你必须非常努力地推动GCC抱怨它;我使用-std=c99 -pedantic并且仅使用-pedantic警告'结构没有成员'。

在我看来,你会更好(更严格的便携性):

typedef struct tagFOO FOO;

或者,甚至使用:

typedef struct FOO FOO;

答案 2 :(得分:0)

最坏情况:HANDLE实际上是64位整数值,FOO*是32位指针。转换丢失信息,检查foo != NULL是错误的(因为它可能是句柄的有效值)。

这确实非常可疑。