Handling bit arrays in C without padding - c

I'm writing a C program that runs on the Altera NIOS II processor. The program has to interface to a VHDL module on an FPGA test board through a specific memory location. My interface is provided through a Macro, which specifies a base memory address. The VHDL programmer has allocated 32-bits of memory off of that base address, which I'm to fill with binary data separated into four "elements", i.e. [0-11|12-15|16-23|24-31].
My question is, what is the best way to handle these array "elements" as separate data types. I'd like to declare the entire array as a structure to handle the data and declare the different fields using bit-fields, but it's my understanding that this will introduce padding into the 32 bit array.

it's my understanding that [using bit fields] will introduce padding into the 32 bit array
Using bit fields will not introduce padding, unless you explicitly request it: language standard prohibits the compier from padding in between bit fields:
C99 Standard, section 6.7.2.1.10: If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.
You can force padding to happen by specifying a bit field of zero width, like this:
struct hw_reg {
int a:10;
int :0; // Yes, this is legal.
int b:6;
};
In your case, sufficient space remains after the first 12 bits to allocate the next four, so there will be no padding. If you needed to split the register differently (say, 12-5-7-8), the use of padding would be implementation-defined.

binary data separated into four "elements", i.e.
[0-11|12-15|16-23|24-31].
I'd try as
struct vhdl_data {
uint32_t a : 12; // bits 0-11
uint32_t b : 4; // bits 12-15
uint32_t c : 8; // bits 16-23
uint32_t d : 8; // bits 24-31
};

Related

Structure padding in c size related query [duplicate]

This question already has answers here:
Structure padding and packing
(11 answers)
Closed 6 days ago.
I find a lot of ambiguity while working on structure padding in C.
I need the following :
Trustworthy resource or url to understand structure padding in c.
How memory is allocated to structures, by individual members of by pages (like 1 page=4 bytes for 32 bit machines and 8 bytes for 64 bit machines).
#include <stdio.h>
typedef struct
{
unsigned short Flag;
char DebounceSamples;
unsigned short Device;
char *BufferPtr;
char *OverridePtr;
} IoHwAb_DIN_DescriptorType;
int main()
{
IoHwAb_DIN_DescriptorType tt;
printf("%lu",sizeof(tt));
return 0;
}
When I execute this I see the output is 24 for the size of struct. I kind of understand why, but also I have a confusion. I need a clear explanation on this.
Each object type has some alignment requirement. Any object of that type is required to start at an address that is a multiple of the alignment requirement. Each C implementation may determine its own alignment requirements for its object types, but alignment requirements are usually set for hardware efficiency. Most notably, the requirements are set so that any correctly aligned object will not cross a memory boundary that requires an extra load or store operation.
For example, consider hardware that can perform transfers of data between the processor and memory in four-byte chunks starting at addresses that are multiples of four bytes. The hardware can transfer bytes addressed 0-3 in one operation, bytes addressed 4-7 in one operation, bytes address 8-11 in one operation, and so on. However, if we wanted bytes 6-9, that would require two memory transfer operations, one to get byes 4-7 and one to get bytes 8-11. In this hardware, we would set the alignment requirement of a four-byte int to be four bytes, so that all four bytes of the int are always inside one of these aligned groups.
For a two-byte short, we could allow a short object to be in bytes 5-6 in memory, because we can fetch both bytes in one operation (loading bytes 4-7). However, if we have an array of short with the first in bytes 5-6, then the next would be in 7-8, and we cannot fetch that short in one operation; we would have to get bytes 4-7 and 8-11. So, to ensure that short objects always have good alignment, we require them to start at multiples of two bytes.
Once the alignment requirements are set, the algorithm usually used to lay out a structure is:
Each member in the structure has some size s and some alignment requirement a.
The compiler starts with a size S set to zero and an alignment requirement A set to one (byte).
The compiler processes each member in the structure in order:
Consider the member’s alignment requirement a. If S is not currently a multiple of a, then add just enough bytes to S so that it is a multiple of a. This determines where the member will go; it will go at offset S from the beginning of the structure (for the current value of S).
Set A to the least common multiple1 of A and a.
Add s to S, to set aside space for the member.
When the above process is done for each member, consider the structure’s alignment requirement A. If S is not currently a multiple of A, then add just enough to S so that it is a multiple of A.
The size of the structure is the value of S when the above is done.
Additionally:
If any member is an array, its size is the number of elements multiplied by the size of each element, and its alignment requirement is the alignment requirement of an element.
If any member is a structure, its size and alignment requirement are calculated as above.
If any member is a union, its size is the size of its largest member plus just enough to make it a multiple of the least common multiple1 of the alignments of all the members.
The rules above follow largely from logic; they put each member where it must be to satisfy alignment requirements without using more space than necessary. The C standard allows implementations to add more padding between elements or at the end of the structure, but this is generally not done. (It could be done for special purposes, such as adding padding during debugging to test whether some bug manifests without padding but not with it, to give clues about the nature of the bug.)
In your structure, char is one byte with alignment requirement one byte, unsigned short is probably two bytes with requirement two bytes, and char * is probably eight bytes with requirement eight bytes. Then the structure layout proceeds:
S is zero and A is one byte.
No padding is needed, since S is a multiple of the two-byte requirement for unsigned short Flag.
unsigned short Flag adds two to S and makes A two bytes.
No padding is needed, since S is a multiple of the one-byte requirement for char DebounceSamples.
char DebounceSamples adds one to S, making it three, and does not change A, leaving it two bytes.
One byte of padding is needed, because S is not a multiple of the two-byte requirement for unsigned short Device, so S is increased to four.
unsigned short Device adds two to S, making it six, and does not change A, leaving it two bytes.
Two bytes of padding are needed, because S is not a multiple of the eight-byte requirement for char *BufferPtr, so S is increased to eight.
char *BufferPtr adds eight to S, making it 16, and changes A to eight bytes.
No padding is needed because S is a multiple of the eight-byte requirement for char *OverridePtr.
char *OverridePtr adds eight to S, making it 24, and does not change A.
At the end, the size of the structure is 24 bytes, and its alignment requirement is eight bytes.
Footnote
1 I have worded this for a general case as using the least common multiple of alignment requirements. However, since alignment requirements are always powers of two, the least common multiple of any set of alignment requirements is the largest of them.

Are bits in the structure guaranteed

I have a question related to structure bit fields, please see below as I am a bit clueless on which keywords I should use to best describe my issue:
Context: I am writing a disassembler for MIPS R3000A Assembly Instructions, the one that were used for Playstation Programs in the early 2000.
Issue: I would like to know if in this code:
struct Instruction {
u32 other:26;
u32 op:6;
};
//main:
Instruction instruction = *(Instruction*)(data + pc);
printf("%02x\n", instruction.op);
it is guaranteed that all compilers, using little endianness, will always using the op:6 bit-fields to store the first 6 MSB ? (which is a bit counter intuitive, you would assume that the last 6 bits are stored in the op bit field)
It is an alternative to the following code:
static uint32_t get_op_code(uint32_t data) {
uint16_t mask = (1 << 6) - 1;
return (data >> 26) & mask;
}
//main:
uint32_t instruction = *(uint32_t*)(data + pc);
uint32_t op = get_op_code(instruction);
printf("%02x\n", op);
It is working fine on my side and it seems slightly faster using the structure approach, not to mention that is is more intuitive and clear, but I am afraid that it would not be guaranteed that the 6 first bits are stored in the second bit-field "op" of the structure.
The C standard does not guarantee how bit-fields are arranged. It does require each implementation to define it, so it should be in the documentation for a compiler. Per C 2018 6.7.2.1 11:
An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.

C - Why #pragma pack(1) Consider 6-bit struct member as an 8-bit?

I got stuck about #pragma pack(1) wrong behavior when define a 6-bit field and assumes it as 8-bit. I read this question to solving my problem but it doesn't help me at all.
In Visual Studio 2012 I defined bellow struct for saving Base64 characters :
#pragma pack(1)
struct BASE64 {
CHAR cChar1 : 6;
CHAR cChar2 : 6;
CHAR cChar3 : 6;
CHAR cChar4 : 6;
};
Now I got its size with sizeof, but the result isn't what I expected :
printf("%d", sizeof(BASE64)); // should print 3
Result : 4
I was expect that get 3 (because 6 * 4 = 24, so 24 bit is 3 byte)
Event I tested it with 1-bit field instead and got correct size (1-byte) :
#pragma pack(1)
struct BASE64 {
CHAR cChar1 : 2;
CHAR cChar2 : 2;
CHAR cChar3 : 2;
CHAR cChar4 : 2;
};
Actually, why 6-bit assumes 8-bit with #pragma pack(1)?
#pragma pack generally packs on byte boundaries, not bit boundaries. It's to prevent the insertion of padding bytes between fields that you want to keep compressed. From Microsoft's documentation (since you provided the winapi tag, and with my emphasis):
n (optional) : Specifies the value, in bytes, to be used for packing.
How an implementation treats bit fields when you try to get them to cross a byte boundary is implementation defined. From the C11 standard (secion 6.7.2.1 Structure and union specifiers /11, again my emphasis):
An implementation may allocate any addressable storage unit large enough to hold a bitfield. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.
More of the MS documentation calls out this specific behaviour:
Adjacent bit fields are packed into the same 1-, 2-, or 4-byte allocation unit if the integral types are the same size and if the next bit field fits into the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit fields.
The simple answer is: this is NOT wrong behavior.
Packing tries to put separate chunks of data in bytes, but it can't pack two 6-bit chunks in one 8-bit byte. So the compiler puts them in separate bytes, probably because accessing a single byte for retrieving or storing your 6-bit data is easier than accessing two consecutive bytes and handling some trailing part of one byte and some leading part from another one.
This is implementation defined, and you can do little about that. Probably there is an option for an optimizer to prefer size over speed – maybe you can use it to achieve what you expected, but I doubt the optimizer would go that far. Anyway the size optimization usually shortens the code, not data (as far as I know, but I am not an expert and I may well be wrong here).
In some implementations, bit fields cannot span across variable boundaries. You can define multiple bit fields within a variable only if their total number of bits fits within the data type of that variable.
In your first example, there are not enough available bits in a CHAR to hold both cChar1 and cChar2 when they are 6 bits each, so cChar2 has to go in the next CHAR in memory. Same with cChar3 and cChar4. Thus why the total size of BASE64 is 4 bytes, not 3 bytes:
(6 bits + 2 bits padding) = 8 bits
+ (6 bits + 2 bits padding) = 8 bits
+ (6 bits + 2 bits padding) = 8 bits
+ 6 bits
- - - - - - - - - -
= 30 bits
= needs 4 bytes
In your second example, there are enough available bits in a CHAR to hold all of cChar1...cChar4 when they are 1 bit each. Thus why the total size of BASE64 is 1 byte, not 4 bytes:
1 bit
+ 1 bit
+ 1 bit
+ 1 bit
- - - - - - - - - -
= 4 bits
= needs 1 byte

Bit field manipulation disadvantages

I was reading this link
http://dec.bournemouth.ac.uk/staff/awatson/micro/articles/9907feat2.htm
I could not understand this following statements from the link, Please help me understand about this.
The programmer just writes some macros that shift or mask the
appropriate bits to get what is desired. However, if the data involves
longer binary encoded records, the C API runs into a problem. I have,
over the years, seen many lengthy, complex binary records described
with the short or long integer bit-field definition facilities. C
limits these bit fields to subfields of integer-defined variables,
which implies two limitations: first of all, that bit fields may be no
wider, in bits, than the underlying variable; and secondly, that no
bit field should overlap the underlying variable boundaries. Complex
records are usually composed of several contiguous long integers
populated with bit-subfield definitions.
ANSI-compliant compilers are free to impose these size and alignment
restrictions and to specify, in an implementation-dependent but
predictable way, how bit fields are packed into the underlying machine
word structure. Structure memory alignment often isn’t portable, but
bit field memory is even less so.
What i have understood from these statements is that the macros can be used to mask the bits to left or right shift. But i had this doubt in my mind why do they use macros? - I thought by defining it in macros the portability can be established irrespective of 16-bit or 32-bit OS..Is it true?I could not understand the two disadvantages mentioned in the above statement.1.bit fields may be no wider 2.no bit field should overlap the underlying variable boundaries
and the line,
Complex records are usually composed of several contiguous long integers
populated with bit-subfield definitions.
1.bit fields may be no wider
Let's say you want a bitfield that is 200 bits long.
struct my_struct {
int my_field:200; /* Illegal! No integer type has 200 bits --> compile error!
} v;
2.no bit field should overlap the underlying variable boundaries
Let's say you want two 30 bit bitfields and that the compiler uses a 32 bit integer as the underlying variable.
struct my_struct {
unsigned int my_field1:30;
unsigned int my_field2:30; /* Without padding this field will overlap a 32-bit boundary */
} v;
Ususally, the compiler will add padding automatically, generating a struct with the following layout:
struct my_struct {
unsigned int my_field1:30;
:2 /* padding added by the compiler */
unsigned int my_field2:30; /* Without padding this field will overlap a 32-bit boundary */
:2 /* padding added by the compiler */
} v;

How the size of this structure comes out to be 4 byte

I do have a structure having bit-fields in it.Its comes out to be 2 bytes according to me but its coming out to be 4 .I have read some question related to this here on stackoverflow but not able to relate to my problem.This is structure i do have
struct s{
char b;
int c:8;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}
if int type has to be on its memory boundary,then output should be 8 bytes but its showing 4 bytes??
Source: http://geeksforgeeks.org/?p=9705
In sum: it is optimizing the packing of bits (that's what bit-fields are meant for) as maximum as possible without compromising on alignment.
A variable’s data alignment deals with the way the data stored in these banks. For example, the natural alignment of int on 32-bit machine is 4 bytes. When a data type is naturally aligned, the CPU fetches it in minimum read cycles.
Similarly, the natural alignment of short int is 2 bytes. It means, a short int can be stored in bank 0 – bank 1 pair or bank 2 – bank 3 pair. A double requires 8 bytes, and occupies two rows in the memory banks. Any misalignment of double will force more than two read cycles to fetch double data.
Note that a double variable will be allocated on 8 byte boundary on 32 bit machine and requires two memory read cycles. On a 64 bit machine, based on number of banks, double variable will be allocated on 8 byte boundary and requires only one memory read cycle.
So the compiler will introduce alignment requirement to every structure. It will be as that of the largest member of the structure. If you remove char from your struct, you will still get 4 bytes.
In your struct, char is 1 byte aligned. It is followed by an int bit-field, which is 4 byte aligned for integers, but you defined a bit-field.
8 bits = 1 byte. Char can be any byte boundary. So Char + Int:8 = 2 bytes. Well, that's an odd byte boundary so the compiler adds an additional 2 bytes to maintain the 4-byte boundary.
For it to be 8 bytes, you would have to declare an actual int (4 bytes) and a char (1 byte). That's 5 bytes. Well that's another odd byte boundary, so the struct is padded to 8 bytes.
What I have commonly done in the past to control the padding is to place fillers in between my struct to always maintain the 4 byte boundary. So if I have a struct like this:
struct s {
int id;
char b;
};
I am going to insert allocation as follows:
struct d {
int id;
char b;
char temp[3];
}
That would give me a struct with a size of 4 bytes + 1 byte + 3 bytes = 8 bytes! This way I can ensure that my struct is padded the way I want it, especially if I transmit it somewhere over the network. Also, if I ever change my implementation (such as if I were to maybe save this struct into a binary file, the fillers were there from the beginning and so as long as I maintain my initial structure, all is well!)
Finally, you can read this post on C Structure size with bit-fields for more explanation.
int c:8; means that you are declaring a bit-field with the size of 8 bits. Since the alignemt on 32 bit systems is normally 4 bytes (=32 bits) your object will appear to have 4 bytes instead of 2 bytes (char + 8 bit).
But if you specify that c should occupy 8 bits, it's not really an int, is it? The size of c + b is 2 bytes, but your compiler pads the struct to 4 bytes.
They alignment of fields in a struct is compiler/platform dependent.
Maybe your compiler uses 16-bit integers for bitfields less than or equal to 16 bits in length, maybe it never aligns structs on anything smaller than a 4-byte boundary.
Bottom line: If you want to know how struct fields are aligned you should read the documentation for the compiler and platform you are using.
In generic, platform-independent C, you can never know the size of a struct/union nor the size of a bit-field. The compiler is free to add as many padding bytes as it likes anywhere inside the struct/union/bit-field, except at the very first memory location.
In addition, the compiler is also free to add any number of padding bits to a bit-field, and may put them anywhere it likes, because which bit is msb and lsb is not defined by C.
When it comes to bit-fields, you are left out in the cold by the C language, there is no standard for them. You must read compiler documentation in detail to know how they will behave on your specific platform, and they are completely non-portable.
The sensible solution is to never ever use bit fields, they are a reduntant feature of C. Instead, use bit-wise operators. Bit-wise operators and in-depth documented bit-fields will generate the same machine code (non-documented bit-fields are free to result in quite arbitrary code). But bit-wise operators are guaranteed to work the same on any compiler/system in the world.

Resources