Подтвердить что ты не робот

Использование переопределения указателя void для указателя на анонимную структуру?

Я работал с 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" намекает?

4b9b3361

Ответ 1

Библиотека использует информацию, скрывающуюся во внутреннем объекте данных за адресом, хранящимся в EFI_HANDLE. Но при этом они делают код более восприимчивым к случайным ошибкам.

В C, void* прозрачно применяется к любому другому не-t20 > неконстантическому типу данных данных без предупреждения (это по языковому дизайну).

Использование непрямого указателя гарантирует, что EFI_HANDLE используется только там, где EFI_HANDLE принадлежит. Проверка типа компилятора ударяет вас в пах, когда вы передаете его где-то в другом месте, а не EFI_HANDLE, а скорее указатель на что-то другое.

Ex: As void*, это будет компилироваться без предупреждения или ошибки

#include <string.h>

#define EFI_HANDLE void*

int main()
{
    EFI_HANDLE handle = NULL;

    strcpy(handle, "Something");
}

Изменение псевдонима на:

typedef struct {} *EFI_HANDLE;

будет извлекать следующую ошибку "ошибка несовместимого типа указателя".

Наконец, в качестве анонимной структуры нет бессмысленного имени тега структуры, добавляющего к уже загрязненному пространству имен, которое вы можете использовать (случайно или нечестно).

Ответ 2

Это не анонимная структура, а структура без тега.

Анонимная структура может существовать только как член другой структуры,
и он также не должен иметь тег 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)
Неименованный элемент, спецификатор типа которого является спецификатором структуры без тега, называется анонимная структура; неназванный член, спецификатор типа которого является спецификатором объединения с no tag не называется анонимным объединением. Члены анонимной структуры или объединения считаются членами структуры или объединения. Это относится рекурсивно, если содержащая структура или объединение также анонимно