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 шт):
Нет, void * никак не влияет на запрет каламбуров типизации.
Поскольку библиотека ничего не знает о том, что же сокрыто под указателем
data, библиотека имеет полное право интерпретировать данные так, как посчитает нужным. То есть,dataможет указывать на объект типа, отличного отObject, да хоть просто в буфер байтов.
Все правильно. Формально, если он указывает не на настоящий Object, будет каламбур типизации и неопределенное поведение. На практике, если функция лежит в отдельной библиотеке (или просто в другой единице трансляции, если link-time оптимизация не включена), то компилятор никогда об этом не узнает, и ничего не сломается.
A
void*pointer can be converted into any other type of data pointer.
Тут видимо просто имеют в виду, что void * можно скастовать к любому другому указателю "на данные" (т.е. не на функции и не на члены класса).