ccompiler-warnings

Bit Fields access in C


I am trying to access bit fields:

Below is the code which works fine and gives expected result but throws compiler warnings which I have mentioned below.

#include <stdio.h>
#include <stdint.h>


struct status_type_one{
unsigned delta_cts : 1;// lsb
unsigned delta_dsr : 1;
unsigned tr_edge : 1 ;
unsigned delta_rec : 1;
unsigned cts : 1;
unsigned dsr : 1;
unsigned ring : 1;
unsigned rec_line : 1;// msb
} status_one;

struct status_type_two {
unsigned : 4; // lsb 4 bits
unsigned cts : 1; //bit 5
unsigned dsr : 1; // bit 6
} status_two;



int main(void)
{
  status_one.delta_cts=1;
  status_one.delta_dsr=0;
  status_one.tr_edge=1;
  status_one.delta_rec=0;
  status_one.cts=1;
  status_one.dsr=0;
  status_one.ring=1;
  status_one.rec_line=1;

  printf("The value of status_one is %x\n",status_one);  // warning here

  status_two.cts=1;
  status_two.dsr=1;

  printf("The value of status_one is %d\n",status_two);  // warning here



    return 0;
    }

But I am getting below warning:

$ gcc -Wall Bit_Fields.c -o Bit_Fields
Bit_Fields.c: In function `main':
Bit_Fields.c:35: warning: unsigned int format, status_type_one arg (arg 2)
Bit_Fields.c:35: warning: unsigned int format, status_type_one arg (arg 2)
Bit_Fields.c:40: warning: int format, status_type_two arg (arg 2)
Bit_Fields.c:40: warning: int format, status_type_two arg (arg 2)

The Output is correct as shown below

$ ./Bit_Fields
The value of status_one is d5
The value of status_one is 48

Can anyone please tell, What the warning is about and how to resolve it?

Thanks


Solution

  • The typical way to solve this is to have an integer-type union value, e.g:

    union status_type_one
    {
       struct status_type_one{
           unsigned delta_cts : 1;// lsb
           unsigned delta_dsr : 1;
           unsigned tr_edge : 1 ;
           unsigned delta_rec : 1;
           unsigned cts : 1;
           unsigned dsr : 1;
           unsigned ring : 1;
           unsigned rec_line : 1;// msb
       } bits;
       unsigned whole[1];       // Size should match the total bits size.
    } status_one;
    

    Now, your other code would have to change:

    status_one.bits.delta_cts=1;
    status_one.bits.delta_dsr=0;
    status_one.bits.tr_edge=1;
    ... etc ...
    

    and the print:

    printf("The value of status_one is %x\n",status_one.whole[0]);
    

    [Obviously, if the struct is more than one item in whole, you need to either loop or pass several values to printf]

    What you are doing may well appear to work, but you are not really supposed to pass a STRUCT to a printf function, and there's no telling what that does if you use more than one machine word worth of data, or what happens on a 64-bit machine, etc, etc.