ПроблемаПроблема происходит, когда бросок выполняется между указателем на тип объекта и указателем на различный тип объекта.
РискЕсли указатель на объект брошен в указатель на различный объект, получившийся указатель может быть неправильно выровнен. Неправильное выравнивание вызывает неопределенное поведение.
Даже если преобразование производит указатель, который правильно выравнивается, поведение может быть не определено, если указатель используется, чтобы получить доступ к объекту.
Исключение: можно преобразовать указатель на тип объекта в указатель на один из следующих типов:
char
signed char
unsigned char
Пример - несовместимый: бросьте к указателю, указывающему на объект более широкого типаsigned char *p1;
unsigned int *p2;
void foo(void){
p2 = ( unsigned int * ) p1; /* Non-compliant */
}
В этом примере, p1
может указать на signed char
объект. Однако p1
брошен к указателю, который указывает на объект более широкого типа, unsigned int
.
Пример - несовместимый: бросьте к указателю, указывающему на объект более узкого типаextern unsigned int read_value ( void );
extern void display ( unsigned int n );
void foo ( void ){
unsigned int u = read_value ( );
unsigned short *hi_p = ( unsigned short * ) &u; /* Non-compliant */
*hi_p = 0;
display ( u );
}
В этом примере, u
unsigned int
переменная. &u
брошен к указателю, который указывает на объект более узкого типа, unsigned short
.
На машине с обратным порядком байтов, операторе *hi_p = 0
попытки очистить высокие биты ячейки памяти, что &u
точки к. Но, от результата display(u)
, вы можете найти, что высокие биты не были очищены.
Пример - совместимый: бросьте добавление спецификатора типаconst short *p;
const volatile short *q;
void foo (void){
q = ( const volatile short * ) p; /* Compliant */
}
В этом примере, обоих p
и q
может указать на short
объекты. Бросок между ними добавляет volatile
спецификатор только и поэтому совместим.