Ответ 1
void *
не имеет ничего общего с типом. Его основными целями являются:
-
Разрешить общие операции выделения и освобождения, которые не заботятся о типе объекта, который хранит его вызывающий (например,
malloc
иfree
). -
Чтобы вызывающий мог передать указатель на произвольный тип с помощью функции, которая будет передавать ее обратно через обратный вызов (например,
qsort
иpthread_create
). В этом случае компилятор не может применять проверку типов; это ваша ответственность при написании вызывающего и обратного вызова, чтобы гарантировать, что обратный вызов обращается к объекту с правильным типом.
Указатели на void
также используются в нескольких местах (например, memcpy
), которые фактически работают с объектом в качестве наложенного представления unsigned char []
для объекта. Это можно рассматривать как тип-punning, но это не нарушение псевдонимов, потому что типам char
разрешено псевдонизировать что-либо, чтобы получить доступ к его представлению. В этом случае unsigned char *
также будет работать, но void *
имеет то преимущество, что указатели автоматически преобразуются в void *
.
В вашем примере, поскольку исходный тип int
, а не объединение, не существует законного способа ввода слов и доступа к нему как short
. Вместо этого вы можете скопировать значение x
в объединение, выполнить четко определенный тип-punning, а затем скопировать его обратно. Хороший компилятор должен полностью опустить копию. В качестве альтернативы вы можете разбить запись на записи char
, а затем это будет юридическое сглаживание.