C++, действительно ли каламбур типизации через void* - запрещен?

Подскажите, пожалуйста, для чего именно предназначен бестиповый указатель?

Например:

void* p;

Позволяет ли указатель данного типа осуществлять каламбур типизации?

К примеру, если в функцию, которая экспортируется из DLL, необходимо передать указатель на какие-либо данные, то это, чаще всего, осуществляют так:

extern "C" __declspec(dllexport) void cdecl some_function(void* data)
{
    // ...
    Object*const object = reinterpret_cast<Object*>(data);
    // ...
}

Поскольку библиотека ничего не знает о том, что же сокрыто под указателем data, библиотека имеет полное право интерпретировать данные так, как посчитает нужным. То есть, data может указывать на объект типа, отличного от Object, да хоть просто в буфер байтов.

То есть, some_function() ниоткуда не вызывается, поэтому данный вызов не подвержен оптимизациям времени компиляции и времени линковки.

Все обстоит совсем по-другому при написании подобной функции вне обособленной библиотеки. Если подобная функция откуда-то вызывается, и компилятор или линкер это видят, они могут применить оптимизации. И если в data записывается адрес объекта одного типа, а затем преобразуется в адрес объекта другого типа (несовместимого), тогда возникает неопределенное поведение.

Это действительно так?

PS. На MSDN написано следующее:

A void* pointer can be converted into any other type of data pointer.

И это путает меня еще больше.


Ответы (1 шт):

Автор решения: HolyBlackCat

Нет, void * никак не влияет на запрет каламбуров типизации.

Поскольку библиотека ничего не знает о том, что же сокрыто под указателем data, библиотека имеет полное право интерпретировать данные так, как посчитает нужным. То есть, data может указывать на объект типа, отличного от Object, да хоть просто в буфер байтов.

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

A void* pointer can be converted into any other type of data pointer.

Тут видимо просто имеют в виду, что void * можно скастовать к любому другому указателю "на данные" (т.е. не на функции и не на члены класса).

→ Ссылка