12

I have a code which uses bit-fields declared as follows

typedef struct my{
    const char *name;
    uint8_t is_alpha : 1;   
    uint8_t is_hwaccel : 1; 
    uint8_t x_chroma_shift; 
    uint8_t y_chroma_shift; 

} mystr; 

uint8_t is typedef'ed to unsigned char.

Building the code in MS-VS 2008 using this bit fields gives a warning as below:

imgconvert.c(60) : warning C4214: nonstandard extension used : bit-field types other than int.
  1. Is there any problems/potential issues in using bit fields of type other than int? Why the warning?
  2. Are other than int type bit-fileds they allowed by C99 C language specification?
Sisir
  • 4,584
  • 4
  • 26
  • 37
goldenmean
  • 18,376
  • 54
  • 154
  • 211
  • 1
    The warning is pretty self-explanatory: __nonstandard extension used__ ; your code may have portability problems. – Mehrdad Afshari Feb 17 '10 at 12:28
  • @Mehrad:Using type int is useful from portability aspects only if all targets/compiler have same sized ints. – goldenmean Feb 17 '10 at 12:51
  • you are writing about bitfields here, their size is specified in the code. – AProgrammer Feb 17 '10 at 13:27
  • 1
    The problem is not the size of the bitfield (it is specified) but the size of the maximum bitfield (no larger than the type) or the padding (two 1 bits are packed in 8bit int with 6 unused bits, for a int it would be 2 used and 30 free). – eckes Mar 07 '16 at 22:39
  • Another thread you may be interested in: https://stackoverflow.com/questions/54719855/unresolved-external-symbol-aullshr-when-optimization-is-turned-off – smwikipedia Feb 18 '19 at 03:31

3 Answers3

6

1] Is there any problems/potential issues in using bit fields of type other than int? Why the warning?

Since bit-fields are low-level, there may be issues with portability if you are using non-standard types. Hence the warning -- note it is still a warning and not an error.

2] Are other than int type bit-fileds they allowed by C99 C language specification?

From the draft of C99:

6.7.2.1 Structure and union specifiers

4 A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type.

Community
  • 1
  • 1
dirkgently
  • 108,024
  • 16
  • 131
  • 187
  • 11
    Isn't "some other implementation-defined type" remarkably useless in a standards document? –  Feb 17 '10 at 12:34
  • @Neil Butterworth: ATM, I just have the draft. Will need to look up the actual though. But, yes, I guess you are right. – dirkgently Feb 17 '10 at 12:42
  • @dirkgently: Using type int is useful from portability aspects only if all targets/compiler are guaranteed to have same sized ints. Is this a reasonable assumption. I dont know thats why i am asking. – goldenmean Feb 17 '10 at 12:51
  • @goldenmean: No, the standard gurantess only `char` to have the same size across all machines. The size of an `int`is defined only as a range so it's not very useful from the portability perspective. The `stdint` header was added for this purpose to C99. I guess you should be okay with the warning. – dirkgently Feb 17 '10 at 13:01
  • 1
    @dirkgently, sizeof(char) is one, but that doesn't mean CHAR_BIT is the same on all platforms. – AProgrammer Feb 17 '10 at 13:31
  • @Neil, assuming there is an implementation for which they are valid, those words makes a program which use another types conforming (conforming, not strictly conforming). – AProgrammer Feb 17 '10 at 13:36
  • @goldenmean: `int` is portable, even on platforms with other sized `int`s. When dealing with bitfields, the compiler could pack them into a single `int` or give them their own `int`. If you're trying to create a struct to match a file format or protocol format, don't use bitfields. – tomlogic Feb 17 '10 at 16:49
  • @Neil: I don't think so. While I personally prefer languages that have a stricter definition than that, I see the use in allowing implementations to support other types as well. The ones mentioned here are the ones that every implementation *must* support. – Joachim Sauer Feb 17 '10 at 16:52
  • @dirkgently: TI's C55xx compiler's char type for example is 16 bit. sizeof(char) is 1 as required by teh standard, but CHAR_BIT is 16. The architecture does not support 8-bit addressability. Makes porting third-party code a pain. – Clifford Jul 06 '10 at 12:43
  • What is the alignment difference between unsigned and signed, anyway? – eckes Mar 07 '16 at 22:42
2

Why not use int? The actual implementation of bitfields varies from compiler to compiler. If you want to write portable code, use int. If you want to create a small structure, or a structure of a fixed number of bytes, or a structure where the bits are in a fixed position, don't use bitfields. Create a uint8_t member called something like flags and define macros to use as bitmasks.

tomlogic
  • 11,489
  • 3
  • 33
  • 59
  • You mean `unsigned int`. `uint8_t` is unsigned, `int` is signed, mixing them is no good. – kennytm Feb 17 '10 at 16:49
  • I haven't personally used bitfields in code, but if it's a 1-bit bitfield, does the sign matter? – tomlogic Feb 17 '10 at 16:58
  • 1
    @tomlogic Yes, sign matters. A 1-bit signed field has one sign bit and zero value bits. Hence 1-bit signed fields are expressly forbidden in MISRA C and other standards. – Dana M Nov 24 '20 at 20:23
0

As others have mentioned about portability issues et al, if you didn't know you can just disable the warning via the warning pragma:
https://learn.microsoft.com/en-us/cpp/preprocessor/warning?view=vs-2019

#pragma warning(push)
#pragma warning(disable: 4214) // warning C4214: nonstandard extension used: bit field types other than int
typedef struct my{
    const char *name;
    uint8_t is_alpha : 1;   
    uint8_t is_hwaccel : 1; 
    uint8_t x_chroma_shift; 
    uint8_t y_chroma_shift; 
} mystr; 
#pragma warning(pop)

Also you can disable specific warnings in your project properties but then they are project wide. This way you can control them per data type.

Then if you are ever not sure 100% what kind of binary code MSVC will generate for these either run it in the debugger and look at the "disassembly view" (break on where it gets accessed), or load up your executable (with PDB file for symbols) in a disassembler like IDA Pro, Ghidra, etc.

Sirmabus
  • 636
  • 8
  • 8