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.
Related
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.
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.
Lets say we have this:
int main()
{
int32_t* value = (uint32_t*)malloc(sizeof(uint32_t));
uint32_t array[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
*value = *(uint32_t*)((char*)array + 8);
printf("Value is: %d\n", *value);
return 0;
}
The value in this case would be 3.
Why exactly is that?
If we cast an uint32_t to char, does that mean one char is 4 Byte in uint32_t and therefore
array[9] = {0, 4, !!8!!, 12, 16, 20, 24, 28, 32};
Could someone try to explain this?
When you initialize an array, each initializer sets an element of the array regardless of how many bytes each element takes up.
You machine is probably using little-endian byte ordering. That means that array looks like this in memory:
-----------------------------------------------------------------
| 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 4 | 0 | 0 | 0 | ...
-----------------------------------------------------------------
| [0] | [1] | [2] | [3] | ...
Each value of type uint32_t is 4 bytes long with the least significant byte first.
When you do (char*)array that casts array (converted to a pointer) to a char *, so any pointer arithmetic on a char * increases the address by the size of a char, which is 1.
So (char*)array + 8 points here:
(char*)array + 8 ------------------
v
-----------------------------------------------------------------
| 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 4 | 0 | 0 | 0 | ...
-----------------------------------------------------------------
| [0] | [1] | [2] | [3] | ...
That pointer is then converted to a uint32_t * and dereferenced, so it reads the value 3.
You created array[9] takes 36 bytes. It stores in memory as shown in first row. 3 store as I represented(It varies from compiler).
After you typecast it into char memory is seen as shown in 2nd row.
Now if you add 8 it will go to 8th position that mean after 02, why because, (char*)array + 8 treated as type+8. Here type is char. So it moves only 8 bytes.
Then memory from 8 to 35 type cased to uint32_t and first value stored in *value. So it will 3 only.
This might be a bit long question. I was testing some character arrays in C and so came along this code.
char t[10];
strcpy(t, "abcd");
printf("%d\n", strlen(&t[5]));
printf("Length: %d\n", strlen(t));
Now apparently strlen(&t[5]) yields 3 while strlen(t) returns 4.
I know that string length is 4, this is obvious from inserting four characters. But why does strlen(&t[5]) return 3?
My guess is that
String: a | b | c | d | 0 | 0 | 0 | 0 | 0 | \0
Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
strlen(&t[5]) looks at the length of a string composed of positions 6, 7 and 8 (because the 10th character is a NULL terminating character, right)?
OK, then I did some experimentation and modified a code a bit.
char t[10];
strcpy(t, "abcdefghij");
printf("%d\n", strlen(&t[5]));
printf("Length: %d\n", strlen(t));
Now this time strlen(&t[5]) yields 5 while strlen(t) is 10, as expected. If I understand character arrays correctly, the state should now be
String: a | b | c | d | e | f | g | h | i | j | '\0'
Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
so why does strlen(&t[5]) return 5 this time? I've declared a character array of length 10, should then, by the same logic applied above, the result be 4?
Also shouldn't I be running into some compiler errors since the NULL terminating character is actually in the 11th spot? I'm new into C and would very much appreciate anyone's help.
First let me tell you, your "assumption"
String: a | b | c | d | 0 | 0 | 0 | 0 | 0 | \0
Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
is not correct. Based on your code, The values are only "guaranteed" up to index 4, not beyond that.
For the first case, in your code
printf("%d\n", strlen(&t[5]));
is wrong for various reasons,
you ought to use %zu for a size_t type.
&t[5] does not point to a valid string.
Any (or both) of the above causes undefined behavior and any output cannot be justified.
To elaborate, with a defintion like
char t[10];
strcpy(t, "abcd");
you have index 0 to 3 populated for t, and index 4 holds the null-terminator. The content of t[5] onward, is indeterminate.
Thus, &t[5] is not a pointer to the first element of a string, so cannot be used argument to strlen().
It may run out of bound in search of the null-terminator and experience invalid memory access and, as a side-effect, produce a segmentation fault,
It may find a null-terminator (just another garbage value) within the bound and report a "seemingly" valid length.
Both are equally likely and unlikely, really. UB is UB, there's not justifying it.
Then, for the second case, where you say
char t[10];
strcpy(t, "abcdefghij");
is once again, accessing memory out of bound.
You have all together 10 array elements to store a string, so you can have 9 other char elements, plus one null-terminator (to qualify the char array as a string).
However, you're attempting to put 10 char elements, plus a null character (in strcpy()), so you're off-by-one, accessing out of bound memory, invoking UB.
char t[10]; is not initialized so it just contains garbage values 1). strcpy(t, "abcd"); overwrites the first 5 characters with the string "abcd" and a null terminator.
However, &t[5] points at the first character after the null termination, which remains garbage. If you invoke strlen from there, anything can happen, since the pointer passed is not likely pointing at a null terminated string.
1) Garbage = indeterminate values. Assuming a sane 2's complement system, the address of the buffer t is taken, so the code does not invoke undefined behavior until the point where strlen starts reading outside the bounds of the array t. Reference.
Problem 1:
My guess is that
String: a | b | c | d | 0 | 0 | 0 | 0 | 0 | \0
Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
This assumption is wrong.
The array is not initialized to hold 0 values but contains some "random" garbage.
After copying "abcd" the upper half of the array (t[5] etc.) is still untouched resulting in a "random" length of the string due to undefined behaviour.
Problem 2:
If I understand character arrays correctly, the state should now be
String: a | b | c | d | e | f | g | h | i | j | '\0'
Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
Again wrong.
Your array only holds 10 characters. Theyare at index 0..9. Index 10 is out of bounds.
Your copy operation might result in this layout or it might as well just crash while writing out of bounds.
But this is not checked by the compiler. If you run into problems then it will be during runtime.
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.