2

Hello guys I'm facing another problem, I'm working on single bits and extract data from ascii text. The problem is that the compiler gives me an error about the fact that casting a char (8 bits) to a 4 bit memory field may alter its value.

Obviously that's true but how could I overcome that error?

typedef struct {
struct {
    unsigned int type:        4;
    unsigned int uid:         8;
    unsigned int operation:   4; 
    unsigned int reg:         16;
}header;
char *arg_nm;
} OWL_request;

The complete error:

 error: conversion to 'unsigned char:4' from 'char' may alter its value [-Werror=conversion]

and this is the assignment

request.header.type = (char)(j[0]-65);

j is *char

What I have to do is to get rid of the error without altering compiler flags

Cristofor
  • 2,077
  • 2
  • 15
  • 23
  • 1
    Why are you casting to `char` in the first place? Also, your example displays `unsigned int` but the error mentions `unsigned char` – StoryTeller - Unslander Monica Feb 01 '17 at 09:30
  • Actually for no reason – Cristofor Feb 01 '17 at 09:31
  • 2
    Sidenote: Are you using this for serialization purposes? Using structs, and especially bitfields for that is a very bad idea, due to various implementation specific behaviour. – user694733 Feb 01 '17 at 09:32
  • Well actually what has to be done is to substract one natural number from another then represent it as a char, but given the fact that chars are effectively numbers, thats uneccessary – Cristofor Feb 01 '17 at 09:33
  • I'm sure I'll be in range, but I want to get rid of the error without changing the compiler flags – Cristofor Feb 01 '17 at 09:35

2 Answers2

11

With gcc, you can get rid of the warning by masking the value to the number of bits in the bitfield you assign to, since type is 4 bits, you can do:

request.header.type = (unsigned)(j[0]-65) & 0xf;

(Note that you can find several good arguments as to why you should not use bitfields , see e.g. here , and instead use plain integers and bit twiddling as suggested by @LPs)

Community
  • 1
  • 1
nos
  • 223,662
  • 58
  • 417
  • 506
  • I've got an use case where the input var (let's say ```v```) is more than 1 byte in size. Is this _hack_ correct with respect to endianness? – Oersted Jul 04 '23 at 10:01
2

You should avoid bitfield struct. Use a simple unsigned int and use bitwise operators to assign values:

#define HEADER_VALUE_MASK 0xFu
#define HEADER_VALUE_POS  0
#define HEADER_UID_MASK   0xFu
#define HEADER_UID_POS    4

uint32_t header;

header |= (value & HEADER_VALUE_MASK) << HEADER_VALUE_POS;    
header |= (uid & HEADER_UID_MASK) << HEADER_UID_POS;

An implementation like this take also care of endianness and aligments.

LPs
  • 16,045
  • 8
  • 30
  • 61
  • How does this address the specific question? – 2501 Feb 01 '17 at 09:36
  • I need to I have very limited resources – Cristofor Feb 01 '17 at 09:36
  • This implementation does not increase memory (RAM) footprint. Depending on the compiler the code can be also shorter. – LPs Feb 01 '17 at 09:38
  • @Cristian ths solution proposed here _is_ minimal, efficient and portable. – Jabberwocky Feb 01 '17 at 09:38
  • @MichaelWalz It is less portable as it assumes a 32 bit int. OP's code handles all that. – 2501 Feb 01 '17 at 09:38
  • Yes but given the fact that I have very limited resources I have to be sure that my request fits a 32 bit block not less not more – Cristofor Feb 01 '17 at 09:39
  • 1
    unsigned int, on a 32 bit platform, is 32 bit long. – LPs Feb 01 '17 at 09:40
  • 1
    @Cristian - If that is the case, you should use `uint32_t` from `stdint.h`, for one. – StoryTeller - Unslander Monica Feb 01 '17 at 09:40
  • 3
    @2501 It is more portable than using a bitfield and make the code more readable. At a glance you are sure that the variable is bitfiled and you know exactly value positions and width inside the var. – LPs Feb 01 '17 at 09:42
  • 1
    @LPs This is still less portable. OP's code works on implementations that don't provie uint32_t, which is optional. Your example doesn't. – 2501 Feb 01 '17 at 09:43
  • 1
    @LPs It is less readable. Just look at the amount of code needed, versus a simple assignment for the bit-fields. The bit-fields also encode the type, the struct, so OP's code is more type safe. And implementation of bit-fields don't matter in this example as OP's code isn't relying on it. – 2501 Feb 01 '17 at 09:44
  • 4
    @2501 BTW personal opinions on "What is more readable" are OT. So stop trolling the answer. You downvoted it: that's enough. – LPs Feb 01 '17 at 09:46
  • 2
    My argumentative responses to your comments are not trolling. Beside the arguments for readability, I have provided several objective arguments, (portability, implementation), which you didn't address. – 2501 Feb 01 '17 at 09:47