Отличный способ делать какие-то действия с переменными разных типов. Судя по всему, эта штука внутри себя malloc вызывает, так что можешь или как аноним посоветовал делать, или свои финты с void* использовать, только в этом случае все равно придется писать block = (int*)conv, иначе ошибка будет.
Очень даже имеет. Допустим, твоя функция делает какую-нибудь хрень с числами: скажем, выдает длинный массив unsigned ..., где ... определяется размером size (скажем, при size=1 будет unsigned char, при size=4 — uint32_t и т.д.). Тогда, передав туда адрес указателя нужного типа, ты получишь в него массив.
Но таки симпатичней было бы возвращать этот массив и проверять на !NULL результат.
Проблема уже тут: void ** — указатель на указатель на void не имеет смысла.
имеет. Но этот смысл может быть разным в некоторых платформах (в которых есть разные указатели). В x86 в void** нет никакого криминала, и такой код будет отлично работать на уютном локалхосте. Я гарантирую это!
void ** — указатель на указатель на void не имеет смысла.
Имеет и повсеместно используется. По ссылке идёт лишь речь о том, что на некоторых машинах (Eclipse MV, HP 3000) из далеких 80х размер char* и void* может быть разным.
При том, что взяитие адресса — это частный случай арифметики.
Оно просто не имеет смысла, ты не можешь сделать v++, если v это void *, т.к. это подразумевает, что компилятор знает размер того, на что ссылается ссылка.
А void ** не имеет смысла в двойне. Т.к. void *** == void ** == void *
При том, что взяитие адресса — это частный случай арифметики. Оно просто не имеет смысла, ты не можешь сделать v++, если v это void *, т.к. это подразумевает, что компилятор знает размер того, на что ссылается ссылка.
ты что-то не то курил сегодня. Возьми массив в N элементов. Можно адрес взять? Можно. А можно сделать v++? Нельзя, если ты не знаешь N.
Можешь рассматривать void* как массив из нескольких char'ов. Точное количество этих char'ов неизвестно.
leaq -16(%rbp), %rcx ;; сохраняем адрес p в rcx
leaq -4(%rbp), %rdx ;; сохраняем адрес x в rdx
movl $5, -4(%rbp) ;; помещаем пятёрку в x
movq %rdx, -16(%rbp) ;; помещаем rdx (=адрес x) в p
movq %rcx, -24(%rbp) ;; помещаем rcx (=адрес p) в pp
При том, что взяитие адресса — это частный случай арифметики.
Это не имеет смысл с точки зрения логики. Это как сказать, что поскольку яблоки и апельсины складывать нельзя, то брать из ящика яблоки или апельсины тоже нельзя.
Оно просто не имеет смысла, ты не можешь сделать v++, если v это void *, т.к. это подразумевает, что компилятор знает размер того, на что ссылается ссылка.
Но ведь компилятор совершенно точно знает размер значения, на которое ссылается void**. Это sizeof(void*). Он равен sizeof(int*), sizeof(char*) и sizeof(uint32_t*), потому что размер всех указателей (на данные, по крайней мере, в отличие от указателей на функции) должен быть одинаковый.
Поправка. Стандарт в самом деле не гарантирует, что все указатели будут одинакового размера, но основной мой тезис остаётся в силе: указатель на void, в отличие от самого void, должен иметь вполне конкретный размер.
А void ** не имеет смысла в двойне. Т.к. void *** == void ** == void *
Ага, а если я массив указателей опишу? А если это будут нетипизированные указатели? Вот прямо так:
void *untyped_pointers_vector[10];
Напомню, a[ b ] есть то же самое, что *(a+b), причём всегда. Если бы void** был тем же самым, что и void* (над которым, как совершенно верно подмечено, запрещена арифметика — но лишь потому, что sizeof(void) не определён, чего никак нельзя сказать о sizeof(void*)), то к элементам вышеописанного массива было бы невозможно обращаться, то есть ваще никак.