Предупреждение о компиляции для void ** и void * - PullRequest
4 голосов
/ 22 сентября 2011

У меня есть вопрос, касающийся void* и void**, и я знаю, что это своего рода старый вопрос, который был задан (несколько) раньше в stackoverflow.Таким образом, вопрос заключается в следующем:

Когда я компилирую этот код с помощью gcc 4.4.3 под Ubuntu 10.10, я получаю следующее предупреждение:

zz.c: In function ‘main’:
zz.c:21: warning: passing argument 1 of ‘bar’ from incompatible pointer type
zz.c:9: note: expected ‘void **’ but argument is of type ‘float **’

почему это нормально для передачипеременная x в качестве аргумента функции foo (), но нельзя передавать переменную y в качестве аргумента функции bar ().Я могу исправить это, явно приведя обе переменные к void* и void**, как и ожидалось.

void foo (void* a){
}

void bar(void **a){
     *a = (float *) malloc(100*sizeof(float));
}

int main (){

    float *x = (float*) malloc(100*sizeof(float));
    foo(x);
    free(x);

    float *y;
    bar(&y);
    free(y);

    return 0;
}

Ответы [ 3 ]

10 голосов
/ 22 сентября 2011

void *a означает, что a указывает на объект неизвестного типа.Однако a сам по себе не является неизвестным типом, поскольку известно, что a имеет тип void*.Только объект, на который указывает a, имеет неизвестный тип.

void **a означает, что a указывает на объект типа void*.Объект, на который указывает *a, имеет неизвестный тип, но сам объект *a является указателем с типом void*.

&y является указателем на объект типа float*.&y не является указателем на объект типа void*.

6 голосов
/ 22 сентября 2011

Стандарт C ++ допускает неявное преобразование любого указателя в a void*.Но void** - это не то же самое, что void*;это указатель на void*.Следовательно, он подпадает под правила для регулярных преобразований указателей (то есть: запрещено без приведения, за некоторыми исключениями).

3 голосов
/ 22 сентября 2011

Добавляя к информации в других ответах, void* действует как универсальный тип указателя в C. Есть общие для него вещи: любой указатель (кроме типа указателя на функцию) может быть преобразован в void * и обратно без потери информации, и выражение указателя (опять же, отличное от указателя на функцию) может быть неявно преобразовано в void*. (C ++ имеет немного другие правила.)

Вы можете подумать, что void** - это тип общего указателя на указатель, но это не так. Это указатель на определенный тип, а именно на void*. На самом деле, C не имеет общего типа указатель-указатель. Но у него есть универсальный тип указателя, поэтому любой код, который пытается использовать void** в качестве универсального типа указатель-на-указатель, может просто использовать void*.

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