Построение из моей предыдущей публикации ...
ВНИМАНИЕ: Все адреса памяти здесь вымышленные. Я просто делаю их, чтобы проиллюстрировать точку.
Дано:
int data[] = {10,11,12};
Теперь у нас есть:
0xffff0000-0xffff0003 with a value of (int)(10)
0xffff0004-0xffff0007 with a value of (int)(11)
0xffff0008-0xffff000b with a value of (int)(12)
(я не собираюсь перейти к порядку байтов с прямым порядком байтов и байтов с прямым порядком байтов здесь.)
Если у нас есть:
int * p = data;
Теперь у нас есть другая область памяти где-то еще, скажем:
0xaaaa0000-0xaaaa0003 with a value of (int*)0xffff0000
Мы можем использовать p [1] [или * (p + 1)] для ссылки * (int *) (0xffff0004) [= 11] на sizeof (int) = 4 и 0xffff0000 + sizeof (int) = 0xffff0004.
Если у нас есть:
void * v = data;
Теперь у нас есть другая область памяти где-то еще, скажем:
0xbbbb0000-0xbbbb0003 with a value of (void*)0xffff0000.
Однако void не имеет никакой связанной информации о sizeof (). Мы не можем увеличивать или уменьшать указатель. Мы не можем разыменовать доступ к данным, хранящимся в 0xffff0000. Мы можем использовать это значение только как необработанный адрес памяти.
Если мы хотим использовать данные, хранящиеся в (void *) 0xffff0000, нам сначала нужно привести их к соответствующему типу.
Тем не менее, (void *) все еще весьма полезен в качестве средства передачи адресов в произвольные структуры данных вокруг. Например, memset (). Не имеет значения, обнуляю ли я struct tm или struct sockaddr . Нам просто нужен указатель на структуру и ее размер.
(Это должно быть само собой разумеющимся, но ... Остерегайтесь использования memset для обнуления экземпляра класса и, при этом, перезаписи таблицы виртуальных указателей.)