Void ** общий указатель?

void * является общим указателем, но как насчет void **? Является ли void ** общим указателем?

Можем ли мы отображать void ** на int **, char ** и так далее.

Я был бы благодарен за переполнение семейства стека за любую информацию об этом.

Ответы

Ответ 1

Нет. void** является указателем на void*, и больше ничего. Только void* действует как общий указатель.

Обратите внимание, что на самом деле попытка его, вероятно, даст согласованные результаты, но только вышеизложенное предусмотрено стандартом, все остальное - Undefined Behavior и может сработать без пощады.

Ответ 2

void** является указателем на void*. Помимо того, что это поведение undefined (которое в то время как страшно, поведение часто определяется вашим компилятором), это также огромная проблема, если вы выполняете reinterpret_cast:

int x = 3;
char c = 2;
int* y = &x;
void* c_v = &c; // perfectly safe and well defined
void** z = reinterpret_cast<void**>(&y); // danger danger will robinson

*z = c_v; // note, no cast on this line
*y = 2; // undefined behavior, probably trashes the stack

Указатели на указатели - очень разные звери, чем указатели. Изменения типа, которые относительно безопасны для указателей, небезопасны для указателей на указатели.

Ответ 3

Void ** общий указатель?

void ** не является общим указателем. Стандарт говорит только о void * как общий указатель.

Глава 22: Указатели для указателей:

Одна боковая точка для указателей на указатели и распределение памяти: хотя тип void *, возвращаемый malloc, является общим указателем, подходящим для назначения или указателям любого типа, гипотетический тип void ** не является общим указателем на указатель.


Можем ли мы привести void ** к int **, char ** и так далее.

Нет. Тебе не следует.

C-FAQ говорит, что:

В C нет общего типа указателя на указатель. void * действует как общий указатель только потому, что преобразования (если необходимо) применяются автоматически, когда другим типам указателей присваиваются и void * 's; эти преобразования не могут быть выполнены, если попытка сделана косвенной по значению void **, которая указывает на тип указателя, отличный от void *. Когда вы используете значение указателя void ** (например, когда вы используете оператор * для доступа к значению void *, которому указывают точки void **), компилятор не знает, что значение void * было однажды преобразовано из некоторого другого типа указателя. Он должен предположить, что это не более чем a void *; он не может выполнять никаких неявных преобразований.

Другими словами, любое значение void **, с которым вы играете, должно быть адресом фактического значения void * где-то; отличные от (void **)&dp, хотя они могут закрыть компилятор, являются нелегальными (и могут даже не делать то, что вы хотите, см. также вопрос 13.9). Если указатель, на который указывает void **, не является void *, и если он имеет другой размер или представление, чем void *, тогда компилятор не сможет получить к нему доступ правильно.