Why am I getting this output from a C union with bitfields in my code? - c

Sorry for the non descriptive title - I wasn't sure how to pose this in one line.
I have a data structure, where I have two values: one 14-bit, one 10-bit. I want to be able to access them as bytes in a union. I have the following:
struct test
{
union
{
struct
{
unsigned int a : 14;
unsigned int b : 10;
} fields;
struct
{
unsigned char i0;
unsigned char i1;
unsigned char i2;
} bytes;
} id;
};
Now, when I assign 1 to the value at bytes.i2, I would expect the value at values.b to also assume the value 1. But the value in values.b is actually bytes.i2 shifted left by 2 bits.
int main()
{
struct test x;
x.id.bytes.i2 = 1;
printf("%d", x.id.fields.b); // OUTPUTS 4
return 0;
}
I must be missing some basic principle here, any insight would be helpful!

In little endian, packed structs:
fields a |b
bytes i0 |i1 : |i2
BITS 00000000|000000|00|10000000 i2 = 1; b = 4
BITS 00000000|000000|10|10000000 i1 = 64; b = 1
INDEX 01234567|890123|45|67890123
0 1 2
As you can see b = 0b00000100 (4)

The exact layout and ordering of bitfields in a struct is entirely up to the implementation.
On a little endian machine, the layout of the union most likely looks like this:
|a |b a |b |
|7 6 5 4 3 2 1 0|1 0 d c b a 9 8|a 9 8 7 6 5 4 3|
| i0 | i1 | i2 |
-------------------------------------------------
| | | | | | | | | | | | | | | | | | | | | | | | |
-------------------------------------------------
In this layout, we can see that the 8 low order bits of a are in the first byte, then the 6 high order bits of a and the 2 low order bits of b in the second byte, followed by the high order 8 bits of b in the third byte. This explains the result you're seeing.
Little endian machine will typically also have the bits in little endian format, so if you reverse the order of the bits in each byte above, reflecting the physical representation instead of the logical representation, you can see that the bits of each bitfield are contiguous.

Related

struct padding extra byte after member [duplicate]

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 4 years ago.
#include <stdio.h>
#include <stdint.h>
typedef struct s{
uint8_t a[1];
uint16_t b;
uint8_t c[1];
}s_t;
int main()
{
printf("size = %d", sizeof(s_t));
return 0;
}
I am not sure why the output of this program is 6 bytes and not 5. Why does the compiler pad an extra byte after the last member ? It also seems like, if you make the last member array length 3, the padding makes the size 8. I am unable to explain this since this is not the case for 2 arrays only.
Here is an illustration of the alignment that the compiler generates:
Bytes:
+-----+---------------+
| 0 | a[1] |
+-----+---------------+
| 1 | N/A (padding) |
+-----+---------------+
| 2 | b |
+-----+---------------+
| 3 | b |
+-----+---------------+
| 4 | c |
+-----+---------------+
As 16-bit quantities:
+---+------+----+
| 0 | a[i] | |
+---+------+----+
| 2 | b |
+---+------+----+
| 4 | c | |
+---+------+----+
Processors like to fetch 16-bit quantities from even addresses.
When they are on odd addresses, the computer may have to make 2 16-bit fetches, and extract the unaligned data out of them.
The easy method to eliminate this extra fetch is to add padding bytes so that 16-bit quantities align to even addresses.
A rule of thumb is to place the larger items first, then the smaller.
Applying this rule:
+---+------+
| 0 | b |
+---+------+
| 2 | a[1] |
+---+------+
| 3 | c |
+---+------+
The rule eliminates the need for an extra padding byte.

Efficient concatenation

I am trying to send a message over an LPWAN and one of the issues I am facing is trying to get my message as short as possible.
For example:
I have two integers (0-100) and two Booleans which I have to convert to a Hex to send over the LPWAN. Example:
24
63
True
False
When I concatenate this as 246310 (Hex:3C226), this will take 3 bytes. However, I know that my first integer will never be higher than 50, which is just 6 bits. Is it possible for me to make the hex message shorter than 3C226?
Yes, that should be possible.
The number of bits for your fields are:
integer0: Integer 0..50, 6 bits.
integer1: Integer 0..80, 7 bits.
flag0: Boolean, 1 bit.
flag1: Boolean, 1 bit.
So that's a total of 6 + 7 + 1 + 1 = 15 bits.
Here's how to encode:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | | | |
| | integer0 | integer1 |f0|f1|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
uint16_t encode(uint8_t integer0, uint8_t integer1, bool flag0, bool flag1)
{
return ((uint16_t) integer0 << 9) | ((uint16_t) integer1 << 2) | ((uint16_t) flag0 << 1) | flag1;
}
Using 2 bytes, the value can be stored as:
FirstNum Second 1st bool 2nd bool
<------------> <------------> <------------> <------------>
6bits 7bits 1bit 1bit
Still you are left with 1 bit.
Use left shift << operation to achieve the above.

How to read 2 bits from an array of integers in C language?

U32 BitMap[6] /* 6 words for 96 persons*/
How to make a program having loop to Read 6 words in above bitmap, which we have to read 2 bits per person and store person id and result in tPersonMsg
/* 2 Bits representing 00-> default value, 01->Command Successful, 10->Command Failed
* | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* |<Pr15>|--------------------------------------------------------------------------------------------------------------------------------------|<Pr2>|<Pr1>|<Pr0>|
* | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* |<P31>|--------------------------------------------------------------------------------------------------------------------------------------|<P18>|<P17>|<P16>|
--- similarly for 96 persons*/
to get the result of the persons for which command has failed in following structure.
typedef enum eFinalResult {
Succ= 0,
Fail = 1,
noResponse = 2,
} eFinalResult ;
typedef struct {
U32 Person_Id;
tFinalResult Person_Result;
} tResult;
typedef struct {
U32 NumPersons;
tResult Result[32];
} tPersonMsg;
I am not here to annoy anybody , I am a beginner in C programming
Till now I am trying to make program as follows:
for (i=0; i<6; i++) /* Loop for 6 words*/
{
k = 0;
t= 0x3;
for (j=0; j<31; j+2) /* Loop for bits to reach even position like 0th bit,2nd bit,4th ...and so on*/
{
bits = (a[i] & t) >>j;
k++;
if (a[i] == 2)
{
Command Failed
Person Id = j/2;
}
t = t<<2;
}
}
You have observed that six, 32 bit words are required to hold the data for 96 people: 96 people x 2 bits per person = 192 bits of data, and 192 / 32 = 6 words to hold them.
You can also see that one word will contain 32 / 2 bits per result = 16 results.
So, to find the correct word you divide the person's ID by 16 and the remainder is the 'index' of their result bits within the word. Use the index multiplied by 2 (the number of bits in each result) to shift the word containing the result right, so that the correct result bits are in the least significant position and mask out the remaining bits to obtain the result.
static const U32 BITS_PER_RESULT = 2;
static const U32 RESULTS_PER_WORD = 32 / BITS_PER_RESULT;
static const U32 RESULT_MASK = 0x3;
// The following line is commented out because, although implemented in
// several compilers, it is not part of the C standard (at the moment).
/*static const U32 RESULT_MASK = 0b11;*/
tResult FindResultForPerson(U32 personId)
{
// Find the word in the results array that contains the relevant bits.
U32 resultBits = BitMap[personId / RESULTS_PER_WORD];
// Shift the result word right so that the required bits are in the
// least significant bit position.
resultBits >>= ((personId % RESULTS_PER_WORD) * BITS_PER_RESULT);
// Mask out any more significant bits to leave only the required result.
return resultBits & RESULT_MASK;
}
At some point you will want to ensure that the value passed to the function in personId is not out of range and that the BitMap array contains correctly formatted and valid data, but that's further down the line...
For one bit, for the case when char == 8 bits.
int get1bit(unsigned char *array, int bitpos)
{
int res = array[bitpos >> 3];
res >>= (bitpos & 0x07);
return(res & 0x01);
}
if The real question is to get the value of the two bits at any position.
the answer would be to prepare the mask.
n&(n-1) would always check the value of the last bit(depends on the Arch of the processor also).
or the easy step would be to use a mask of max 32 bits or 64 bits (again depends on the ARCH).
Stackoverflow has many questions related to Masking and get the value of the bits.

improving memory alignment of a structure on 32 bit machine

Correct the alignment of structure below that is bad.
typedef struct{
char *string; // 4 byte (type of address int)
char temp; // 1 byte
short pick; // 2 byte
char temp2; // 1 byte
}hello;
string = 4
temp + pick + temp2(offset 7) = 1+2+1
answer given, good alignment is
char *string; // 4 byte (type of address int)
short pick; // 2 byte
char temp; // 1 byte
char temp2; // 1 byte
string = 4
pick + temp + temp2(offset 7) = 2+1+1
unable to understand the reason that says temp2 should be at offset 7 rather than 8. how? please help
+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
| string | pick | t1| t2|
+---+---+---+---+---+---+---+---+
Using t1 for temp and t2 for temp2, this is the revised layout. The offset of t2 is 7.
For the original structure on a system where n-byte quantities are n-byte aligned, the layout would be:
+---+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B |
+---+---+---+---+---+---+---+---+---+---+---+---+
| string | t1|pad| pick | t2|pad|pad|pad|
+---+---+---+---+---+---+---+---+---+---+---+---+
That's because the 4-byte pointer needs to be 4-byte aligned, so an array of the structure needs each member to be a multiple of 4 bytes.
Thus, in the original structure, the offset of t2 would have been 8, not 7.

If I have a truth table, is there a way of determining the bitwise expression I need for that truth table?

I am attempting to do the following in c:
unsigned int mask;
unsigned int previous;
unsigned int new;
unsigned int out;
for( int i = 0; i < 8; ++i )
{
bool bit_set = GET_BIT( mask, i );
// If the mask bit is true, use the new bit, otherwise use the previous bit
SET_BIT( out, i, GET_BIT( bit_set ? new : previous, i ) );
}
However I think there may be an easier and quicker way using bitwise operations. I have the truth table but I don't know how to get the expression I need.
Truth table is:
m | p | n | o
0 | 0 | 0 | 0
1 | 0 | 0 | 0
0 | 1 | 0 | 1
1 | 1 | 0 | 0
0 | 0 | 1 | 0
1 | 0 | 1 | 1
0 | 1 | 1 | 1
1 | 1 | 1 | 1
How would I go about working this out?
Use Karnaugh Map - there is a solver available online. Pick "three values", enter the expected results for all eight combinations, and use the expression the solver produces:
F(m, p, n) = (p & !n) | (m & n)
EDIT : You can expand this solution to do the whole byte at once, rather than doing it one bit at a time, by using the ~ bitwise NOT operator:
result = (mask & new) | (~mask & previous);
If the mask bit is true, use the new bit, otherwise use the previous
bit
The natural way to express this (to me) is (mask & new) | (~mask & previous). That is to say, mask corresponding bits from new and previous, and add them together using OR.

Resources