#include "stdio.h"
/* array to store data receeived from CAN Bus */
unsigned char a[8] = {0xCD, 0xEF, 0x12, 0x34, 0x50, 0x00, 0x00, 0x00};
typedef struct {
unsigned int a:12;
unsigned int b:12;
unsigned int c:12;
unsigned int unused:28;
}test;
test *tptr;
int main(void)
{
tptr = (test*)( (void*)&a); // is this line braking any aliasing rule
if(tptr->a == 0xCDE)
{
printf("\n data received ok");
}
return 0;
}
Недавно я узнал о проблемах, связанных с псевдонимом указателя в C. Я хочу знать, нарушает ли приведенный выше код какие-либо правила. Может ли это привести к проблемам?
Я знаю, что порядок битового поля зависит от машины и реализации. Однако мой вопрос касается правил псевдонимов указателей, которые я хочу понять более четко.
#include "stdio.h"
необычно. Почему вы не используете#include <stdio.h>
? - person melpomene   schedule 18.06.2016tptr = ...
имеет неопределенное поведение. Во-первых, не гарантируется, чтоB x; (A *)(void *)&x
сделает что-либо разумное (вы только гарантированно сможете преобразоватьvoid *
обратно в исходный типB *
). Во-вторых, даже если это работает, структура может иметь требования к выравниванию. - person melpomene   schedule 18.06.2016sizeof(test)
это12
, а не8
. Возможно, вам нужно упаковать структуру. - person Weather Vane   schedule 18.06.2016tptr->a == 0xFCD
- person Weather Vane   schedule 18.06.2016tptr = (test *)a;
не будет нарушать правило псевдонима. Но у вас есть все проблемы, упомянутые в других комментариях: выравнивание, заполнение, порядок байтов. Кроме того, поскольку сумма размеров ваших битовых полей равна 64, вам, вероятно, следует использоватьuint64_t
вместоunsigned int
(если толькоunsigned int
не является 64-битным в вашей системе). - person user3386109   schedule 18.06.2016struct
с членами типаuint64_t
уменьшил его размер до 8, но все равно вывел0xFCD
. - person Weather Vane   schedule 18.06.2016a
как на 64-битное значение на процессоре с прямым порядком байтов, это0x000000503412efcd
, поэтому битовые поля будут0xfcd
,0x12e
и0x034
. У OP не должно быть этой проблемы на процессоре с прямым порядком байтов. - person user3386109   schedule 18.06.2016uint64_t
. Битовое поле должно иметь тип, который является квалифицированной или неквалифицированной версией_Bool, signed int, unsigned int
или какого-либо другого типа, определяемого реализацией. §6.7.2.1 5 Использование любого другого типа ограничивает переносимость и, возможно, вызывает UB. Лучше всего использоватьunsigned
, как это делал OP. - person chux - Reinstate Monica   schedule 19.06.2016