Тип каламбура с void * без нарушения строгого правила сглаживания в C99
недавно я столкнулся со строгим правилом сглаживания, но у меня возникли проблемы с пониманием того, как использовать void *
для выполнения каламбура типа без нарушения правила.
Я знаю, что это нарушает правило:
int x = 0xDEADBEEF;
short *y = (short *)&x;
*y = 42;
int z = x;
и я знаю, что могу безопасно использовать союз в C99 для каламбуров:
union{
int x;
short y;
} data;
data.x = 0xDEADBEEF;
data.y = 42;
int z = data.x;
но как я использую void *
безопасно выполнить тип-каламбур в C99? Правильно ли следующее:
int x = 0xDEADBEEF;
void * helper = (void *)&x;
short *y = (short *)helper;
*y = 42;
int z = x;
Я подозреваю, что код все равно ломают строгое правило сглаживания, так как память при переменной x
адрес может быть изменен обоими x
и разыменован y
.
если тип-каламбур не определен через void *
, какова цель void *
в C99?
1 ответов
void *
не имеет ничего общего с Type-punning. Его основными целями являются:
для обеспечения универсального распределения и освобождения операций, которые не заботятся о типе объекта, вызывающий объект хранит там (например,
malloc
иfree
).чтобы позволить вызывающему абоненту передать указатель на произвольный тип через функцию, которая передаст его обратно через обратный вызов (например,
qsort
иpthread_create
). В этом случае компилятор не может применять тип проверки; это ваши обязанности при записи вызывающего абонента и обратного вызова убедитесь, что обратный вызов обращается к объекту с правильным типом.
указатели void
также используется в нескольких местах (например,memcpy
), которые на самом деле работают на объекте как наложенные unsigned char []
представление объекта. Это можно рассматривать как каламбур типа, но это не нарушение сглаживания, потому что char
типы разрешены для псевдонима что-либо для доступа к его представление. В этом случае unsigned char *
также будет работать, но void *
имеет то преимущество, что указатели автоматически конвертировать в void *
.
в вашем примере, так как оригинальный типа int
и не союз, нет законного способа ввести каламбур и получить к нему доступ как short
. Вместо этого вы можете скопировать значение x
в объединение, выполните четко определенный тип-каламбур там, а затем скопируйте его обратно. Хороший компилятор должен полностью опустить копию. Кроме того, вы можете разбить запись в char
пишет, а затем это будет юридическое псевдонимы.