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 *
как общий указатель.
Одна боковая точка для указателей на указатели и распределение памяти: хотя тип 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 *
, тогда компилятор не сможет получить к нему доступ правильно.