使用将 void 指针重新定义为指向匿名结构的指针?

Use of redefining void pointer to pointer to an anonymous structure?

我正在处理 UEFI 驱动程序相关的代码,我遇到了这个:

/* EFI headers define EFI_HANDLE as a void pointer, which renders type
* checking somewhat useless. Work around this bizarre sabotage
* attempt by redefining EFI_HANDLE as a pointer to an anonymous
* structure.
*/
#define EFI_HANDLE STUPID_EFI_HANDLE
#include <ipxe/efi/Uefi/UefiBaseType.h>
#undef EFI_HANDLE
typedef struct {} *EFI_HANDLE;

完整的源代码在这个路径 http://dox.ipxe.org/include_2ipxe_2efi_2efi_8h_source.html

这是我第一次接触匿名结构,我无法理解将void *重新定义为指向匿名结构的指针的逻辑。 "bizzare sabotage attempt" 暗示了什么样的 hack?

库正在对 EFI_HANDLE 中保存的地址后面的内部数据对象使用 信息隐藏。但在这样做时,他们使代码 更多 容易受到意外错误的影响。

在 C 中,void* 被透明地转换为 any 其他非 void* 非常量数据指针类型 而没有警告(这是语言设计的)。

使用非空指针类型可确保 EFI_HANDLE 仅在 EFI_HANDLE 所属的位置使用。当您将它传递到不是 EFI_HANDLE 而是指向其他内容的其他地方时,编译器的类型检查会让您感到不安。

例如:作为void*,这将在没有警告或错误的情况下编译

#include <string.h>

#define EFI_HANDLE void*

int main()
{
    EFI_HANDLE handle = NULL;

    strcpy(handle, "Something");
}

将别名更改为:

typedef struct {} *EFI_HANDLE;

将收获随后的 "incompatible pointer type" 编译时错误。

最后,作为一个匿名结构,没有无意义的结构标签名称添加到您可以使用(意外或恶意)的已经污染的名称 space。

这不是匿名结构,而是没有标签的结构。

匿名结构只能作为另一个结构的成员存在,
而且它也不能有标签1

不允许定义没有任何成员的结构。您正在查看的代码使用的是允许这样做的编译器扩展。

库这样做是为了对用户隐藏结构的定义,同时保持类型安全。

然而,有更好的方法来做到这一点。如果你有一个隐藏的结构定义,你仍然可以定义一个指向它的不透明指针,它有一个类型,所以它是类型安全的:

struct hidden    //defined in a file and not exposed
{
    int a;
};

void Hidden( struct hidden* );
void Other( struct other* );
struct hidden* a = NULL;    //doesn't see the definition of struct hidden
Hidden( a );    //it may be used 
Other( a );    //compiler error

1(引自:ISO/IEC 9899:201x 6.7.2.1 结构和联合说明符 13)
类型说明符是不带标记的结构说明符的未命名成员称为 匿名结构;一个未命名的成员,其类型说明符是一个联合说明符 没有标签称为匿名联合。匿名结构或联合的成员 被认为是包含结构或联合的成员。这适用 如果包含的结构或联合也是匿名的,则递归