C Одно и То же имя, Другой Тип

#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. Обратите внимание, что (хотя ваш компилятор может это разрешить), даже если вы используете разные имена , чтение из члена объединения, отличного от последнего написанного, является неопределенным поведением