Хорошо ли определен этот код (Casting HANDLE) - PullRequest
0 голосов
/ 25 июля 2011

В кодовой базе, над которой я сейчас работаю, много примеров кода, подобного этому. Это тонкая оболочка C для OS API.

// 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 ]

2 голосов
/ 25 июля 2011

Стандарт 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

Официально это исключает определение вашей пустой структуры (как и §6.5.2.1 в стандарте C89); в структуре должен быть хотя бы один член. Тем не менее, вы должны довольно сильно толкнуть GCC, чтобы заставить его жаловаться; Я использовал -std=c99 -pedantic и только с -pedantic предупредил, что "struct не имеет членов".

На мой взгляд, вам было бы лучше (более строго переносимым) с:

typedef struct tagFOO FOO;

Или, даже используя:

typedef struct FOO FOO;
2 голосов
/ 25 июля 2011

Цель определения HANDLE - непрозрачный тип, в отношении которого вы не можете делать никаких предположений. На практике мы знаем, что это указатель, и из-за обратной совместимости с Windows это вряд ли когда-либо изменится.

Это действительно имеет огромный запах кода, и если у вас есть половина оправдания, я бы его рефакторинг. Но я не думаю, что вы рискуете, если оставите его в покое.

0 голосов
/ 25 июля 2011

В худшем случае: HANDLE на самом деле является 64-разрядным целочисленным значением, FOO* - это 32-разрядный указатель.Кастинг теряет информацию, а проверка foo != NULL неверна (поскольку это может быть допустимое значение для дескриптора).

Это действительно очень подозрительно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...