13

We are using bit fields to represent elements of a register read from a device.

#include <cstdint> struct Register { uint8_t field : 1; }; int main() { uint8_t byte{0}; // Read from a device Register r; r.field = (byte >> 5) & 0x1; // access bit 5 r.field = (byte >> 7) & 0x1; // access bit 7, warns } 

We are also using the flag -Werror=conversion. For some reason, accessing bit 0 through 6 compiles without warning. However, accessing bit 7 warns for the conversion error: conversion from 'unsigned char' to 'unsigned char:1' may change value [-Werror=conversion].

Any ideas why this might be? Or how to right it in a way that will not warn of a conversion error?

Example here, https://godbolt.org/z/Ghd5ndnKd

6
  • 2
    You told the compiler that you'd like narrowing conversion warnings and that's what it gave you. If you don't like it, get rid of -Wconversion, it was always unreliable and prone to false positives. Commented Jul 11, 2024 at 13:42
  • What if byte is a wider type when you select a bit from it? Commented Jul 11, 2024 at 13:47
  • Potential duplicate of Son of GCC conversion warning when assigning to a bitfield. Most likely a compiler bug, int shift = 7; r.field = (byte >> shift) & 0x1; compiles Commented Jul 11, 2024 at 13:48
  • 1
    bitfields probably don't do what you think they do. They do not model addressable bits, but only create a variable that behaves as if it had N bits. Further the way bitfields behave is compiler specific. My advice, don't use them and do all your bit arithmetic manually ( Commented Jul 11, 2024 at 15:17
  • 3
    @PepijnKramer OP is actually using the bit-field without relying on any underlying representation. Their usage is completely portable. Commented Jul 11, 2024 at 17:31

2 Answers 2

9

It's indeed odd that you are getting 1 warning instead of 2 or 0.

Particularly suspicious wording conversion from 'unsigned char', because your (byte >> 7) & 0x1 has type int.

But since you're asking how to remove the warning, cast the value to a bool.

r.field = ((byte >> 7) & 0x1) != 0; // access bit 7 

or

r.field = bool((byte >> 7) & 0x1); // access bit 7 
Sign up to request clarification or add additional context in comments.

3 Comments

Thus demonstrating that dodging warnings on code whose meaning is well defined is often counter-productive. <g> Yes, these work, but both are misleading and inelegant. Nevertheless, +1.
perhaps add a comment along the line of // convert to bool to silence -Werror=conversion
Somehow this actually generates better code at -O0.
1

It's a diagnostic bug. You can of course work around it, but rather than recognizing the bad diagnostics message, I suggest that you suppress it:

// Suppress error: // "conversion from 'unsigned char' to 'unsigned char:1' may change value" #pragma GCC diagnostic ignored "-Wconversion" r.field = (byte >> 7) & 0x1; #pragma GCC diagnostic pop 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.