#c #struct #union #anonymous-types #bit-fields
#c #структура #объединения #анонимные типы #битовые поля
Вопрос:
У меня есть анонимный, union
который содержит a uint8_t
и битовое поле struct
.
union
{
struct
{
uint8_t ID : 1;
uint8_t C : 4;
uint8_t RM : 1;
uint8_t SWRST : 1;
uint8_t STS : 1;
} ControlByte1;
uint8_t ControlByte1;
};
Как вы можете видеть, вызываются оба экземпляра uint8_t
и struct
ControlByte1
. То, что я пытаюсь сделать, это иметь ControlByte1
значение a uint8_t
, имея возможность доступа к его битам с помощью ControlByte1.ID
, ControlByte1.C
, ControlByte1.RM
ControlByte1.SWRTS
и ControlByte1.STS
. Как и ожидалось, когда я пишу ControlByte1 = ...;
, ... = ControlByte1;
or function(ControlByte1);
, компилятор не имеет возможности узнать, имею ли я в виду ControlByte1
как uint8_t
или struct
. Есть ли какой-нибудь способ сделать это?
Спасибо!
Правка 1:
Я бы просто хотел, чтобы у них было одинаковое имя, потому что ControlByte1 — это однобайтовый байт управления I2C, который содержит поля ID, C, RM, SWRST и STS. Я хочу иметь возможность доступа к ControlByte1 в виде байта, а также получать доступ к его полям по отдельности.
Правка 2:
Возможно, я нашел способ, перегрузив оператор приведения неявного типа.
struct
{
uint8_t ID : 1;
uint8_t C : 4;
uint8_t RM : 1;
uint8_t SWRST : 1;
uint8_t STS : 1;
operator uint8_t*() {return (uint8_t *)this;}
operator uint8_t() {return *(uint8_t *)this;}
} ControlByte1;
Я не уверен, правильно ли я выполняю перегрузку, но она компилируется, я еще не пробовал запускать свой код.
uint8_t var1 = ControlByte1; // Compile
uint8_t *ptr1 = ControlByte1; // Compile
uint8_t *ptr2 = amp;ControlByte1; // Does not compile!!!
var1 = ControlByte1; // Compile
ptr1 = ControlByte1; // Compile
ptr2 = amp;ControlByte1; // Does not compile!!!
Я предполагаю, что это amp;ControlByte1
не компилируется, потому что мне также нужно перегрузить amp;
оператор? Нет необходимости перегружать оператор присваивания, потому что я ничего не присваиваю напрямую ControlByte1
.
Правка 3:
Это имеет больше смысла.
struct
{
uint8_t ID : 1;
uint8_t C : 4;
uint8_t RM : 1;
uint8_t SWRST : 1;
uint8_t STS : 1;
// For implicit casting to uint8_t
operator uint8_t() const
{
return(*(uint8_t *)this);
}
// For implicit casting to uint8_t *
uint8_t * operator amp;() const
{
return((uint8_t *)this);
}
} ControlByte1;
Комментарии:
1. Почему имена не могут быть разными? Чего я не понимаю?
2. Есть способы подделать ее с помощью пользовательского типа, имеющего неявный оператор преобразования, но для данного случая это может быть многовато. Более простой подход переименования объединения во что-то вроде
ControlByte1Fields
, вероятно, был бы лучше и менее запутанным.3. В этом случае лучшим и самым простым решением, как для ее реализации, так и для использования
union
, является просто использование 2 имен.4. Какую актуальную проблему вы пытаетесь решить? Зачем вам это объединение? Почему члены профсоюза должны иметь одно и то же имя?
5. Обратите внимание, что (хотя ваш компилятор может это разрешить), даже если вы используете разные имена , чтение из члена объединения, отличного от последнего написанного, является неопределенным поведением