Problem is solved. Mistake was not to rethink about given datatypes...
The size of following structure is bigger than it should be:
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
struct Y
{
short h;
byte i;
}
#if defined (__GNUC__)
__attribute__((__packed__));
#endif
struct X
{
short a;
byte b;
byte c;
word d;
dword e;
byte f;
byte g;
word h;
short i;
struct Y G[8];
}
#if defined (__GNUC__)
__attribute__((__packed__));
#endif
printf("size of X should be 40 but is %i", sizeof(struct X));
Output:
size of X should be 40 but is 44
I need this structure with a size of 40 Bytes (sum of all elements), 44 is the lowest I can reach. Compiler is GCC C, byte is unsigned char, word is unsigned short and dword is unsigned long. sizeof(Y) is 3. What is the problem here?
The types you define are flawed. Ideally I'd suppose that dword should be double the size of word, but you are defining the two as:
typedef unsigned short word;
typedef unsigned long dword;
And it turns out that on your platform sizeof(unsigned short) is 2, while sizeof(unsigned long) is 8, not 4.
You should really avoid such definitions and use the standard types provided in stdint.h:
byte -> uint8_t
short -> uint16_t
word -> uint16_t
dword -> uint32_t
Finally, your structure declaration is invalid if the macro __GNUC__ is not defined, because you would be missing the final semicolon (;). You can change it to something like this:
#if defined (__GNUC__)
__attribute__((__packed__))
#endif
struct Y
{
uint16_t h;
uint8_t i;
};
Related
I want to parse a chunk of memory into a struct. The problem is that the members are not one after another and there is some padding.
struct foo {
unsigned int a; // # 0
unsigned int junk; // # 0x4
unsigned int b; // # 0x08
unsigned int more_junk;
.........
};
I don't want to assign each member in the struct for every junk that I have. I know that this is possible with unions but not sure for structs.
Update
I'll make another more clear example:
#include <stdio.h>
#include <string.h>
main()
{
struct w {
unsigned long a;
unsigned long b;
unsigned long c;
unsigned long d;
};
struct w *q;
unsigned long array[] =
{
0x11111111,
0x22222222,
0x33333333,
0x44444444
};
q = (struct w*)array;
printf("%x\n", q->a);
printf("%x\n", q->b);
printf("%x\n", q->c);
printf("%x\n", q->d);
}
The output is:
11111111
22222222
33333333
44444444
Lets say that the 3's are junk. The same example:
#include <stdio.h>
#include <string.h>
main()
{
struct w {
unsigned long a;
unsigned long b;
unsigned long d;
};
struct w *q;
unsigned long array[] =
{
0x11111111,
0x22222222,
0x33333333,
0x44444444
};
q = (struct w*)array;
printf("%x\n", q->a);
printf("%x\n", q->b);
printf("%x\n", q->d);
}
The output is:
11111111
22222222
33333333
But it should be:
11111111
22222222
44444444
there is some padding.
Indeed. This is why structs are unsuitable and dangerous to use for memory mapping purposes.
The problem is that the members are not one after another
I don't want to assign each member in the struct for every junk that I have
Not quite sure what you mean. You don't have to assign anything if you don't want to. You do however need to declare room for where the junk bytes will go. Simply declare a dummy variable in the struct which you later ignore, as you do in the very first struct example.
There is no way around this, the only alternative is to use an entirely different data structure such as a plain byte array of raw data. But that would hardly make your program easier to read.
However, if the junk bytes need not be preserved, i.e you are not doing a memory mapping but just some "cherry picking" of the data you are interested in, then you need no junk bytes in the struct. But you will have to assign every member manually, rather than using memcpy.
I know that this is possible with unions
No it isn't, I think you misunderstand how a union works.
From your question :
Members are not one after another : I suggest you to rearrange the members of your struct so that they are in sync with the memory block you wish to copy.
There is some padding : You can prevent the compiler from padding using __attribute__((__packed__)) keyword when you define your struct, which would direct compiler to stop padding.
struct __attribute__((__packed__)) foo {
unsigned int a; // # 0
unsigned int junk; // # 0x4
unsigned int b; // # 0x08
unsigned int more_junk;
.........
};
After this you can either use memcpy() to copy the contents of the memory block to the struct foo variable or if it is struct foo *ptr then directly point to the memory.
For more info on struct padding and packing refer : Structure padding and packing
Hi friend in GCC you can using this in struct for padding :
Type : Width;
this variable hasn't name;
struct foo {
unsigned int a: 4;
unsigned int: 4; //junk;
unsigned int b: 1;
unsigned int: 7; //more_junk;
};
this struct uses 2 byte of sram memory.
FOR your example:
main() {
struct w {
unsigned long a;
unsigned long b;
unsigned long;
unsigned long d;
};
struct w * q;
unsigned long array[] = {
0x11111111,
0x22222222,
0x33333333,
0x44444444
};
q = (struct w * ) array;
printf("%x\n", q -> a);
printf("%x\n", q -> b);
printf("%x\n", q -> d);
}
I have a structure:
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
char payload[1024];
} bar;
I want to find out, at configure time, if I need to insert padding to make 'payload' double-aligned.
Autoconf provides AC_CHECK_SIZEOF(type) and AC_CHECK_ALIGNOF(type), but what I really need is something like AC_CHECK_OFFSETOF(type, member). If the reported offset was not double-aligned, I could introduce enough padding to make it so.
I could run a little test program that reported offsetof(struct bar, payload), but I don't want to introduce a run-time check into my build system (we cross-compile not infrequently).
Using a zero length bitfield might solve this problem without autotool tricks.
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
int64_t : 0; // or long long whatever integer type is sizeof(double)
char payload[1024];
} bar;
You can use AC_COMPUTE_INT:
AC_COMPUTE_INT([payload_offset], [offsetof(struct bar, payload)], ...)
But it would probably be easier just to use an anonymous union to force alignment:
struct foo {
struct {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
union {
char payload[1024];
double dummy; /* for alignment */
};
} bar;
If you don't want to use a union, you can compute the padding in place:
struct foo {
struct header {
int a;
int b;
long len;
unsigned short c;
unsigned short d;
};
char padding[(alignof(double) - 1) - ((sizeof(struct header)
+ alignof(double) - 1) % alignof(double))];
char payload[1024];
} bar;
I don't really think that autoconf can tell you that, as it is a matter of the compiler who decides to add padding or not. So I would think that the only reasonable way would be to compile a program that checks if offset of the member equals to what you think it should be equal.
I am implementing a radio standard and have hit a problem with unions in structure and memory size. In the below example I need this structure to located in a single byte of memory (as per the radio standard) but its currently giving me a size of 2 bytes. After much digging I understand that its because the Union's "size" is byte rather than 3 bits...but havent worked out a way around this.
I have looked at:
Bitfields in C with struct containing union of structs; and
Will this bitfield work the way I expect?
But neither seem to give me a solution.
Any ideas?
Thanks!
#ifdef WIN32
#pragma pack(push)
#pragma pack(1)
#endif
typedef struct three_bit_struct
{
unsigned char bit_a : 1;
unsigned char bit_b : 1;
unsigned char bit_c : 1;
}three_bit_struct_T;
typedef union
{
three_bit_struct_T three_bit_struct;
unsigned char another_three_bits : 3;
}weird_union_T;
typedef struct
{
weird_union_T problem_union;
unsigned char another_bit : 1;
unsigned char reserved : 4;
}my_structure_T;
int _tmain(int argc, _TCHAR* argv[])
{
int size;
size = sizeof(my_structure_T);
return 0;
}
#ifdef WIN32
#pragma pack(pop)
#endif
The problem is that the size of three_bit_struct_T will be rounded up to the nearest byte* regardless of the fact that it only contains three bits in its bitfield. A struct simply cannot have a size which is part-of-a-byte. So when you augment it with the extra fields in my_structure_T, inevitably the size will spill over into a second byte.
To cram all that stuff into a single byte, you'll have to put all the bitfield members in the outer my_structure_T rather than having them as an inner struct/union.
I think the best you can do is have the whole thing as a union.
typedef struct
{
unsigned char bit_a : 1;
unsigned char bit_b : 1;
unsigned char bit_c : 1;
unsigned char another_bit : 1;
unsigned char reserved : 4;
} three_bit_struct_T;
typedef struct
{
unsigned char another_three_bits : 3;
unsigned char another_bit : 1;
unsigned char reserved : 4;
} another_three_bit_struct_T;
typedef union
{
three_bit_struct_T three_bit_struct;
another_three_bit_struct_T another_three_bit_struct;
} my_union_T;
(*) or word, depending on alignment/packing settings.
Two good advices: never use struct/union for data protocols, and never use bit-fields anywhere in any situation.
The best way to implement this is through bit masks and bit-wise operators.
#define BYTE_BIT7 0x80u
uint8_t byte;
byte |= BYTE_BIT_7; // set bit to 1
byte &= ~BYTE_BIT_7; // set bit to 0
if(byte & BYTE_BIT_7) // check bit value
This code is portable to every C compiler in the world and also to C++.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does 'unsigned temp:3' means
A struct's definition goes like this,
typedef struct
{
uint32_t length : 8;
uint32_t offset : 24;
uint32_t type : 8;
} A;
I haven't seen this kind of definition before, what does it mean by :8 and :24?
It's defining bitfields. This tells the compiler that length is 8 bits, offset is 24 bits and type is also 8 bits.
Refer the following link. They are bit-fields. http://www.cs.cf.ac.uk/Dave/C/node13.htmlhttp://en.wikipedia.org/wiki/Bit_field
#include <stdio.h>
typedef unsigned int uint32_t;
#pragma pack(push, 1)
typedef struct
{
uint32_t length : 8;
uint32_t offset : 24;
uint32_t type : 8;
} A;
typedef struct
{
uint32_t length;
uint32_t offset;
uint32_t type;
} B;
#pragma pack(pop)
int main()
{
printf("\n Size of Struct: A:%d B:%d", sizeof(A), sizeof(B));
return 0;
}
Structure A's size will be 5 Bytes where as B's size will be 12 bytes.
This notation defines bit fields, i.e. the size in number of bits for that structure variable.
Why I'm asking this is because following happens:
Defined in header:
typedef struct PID
{
// PID parameters
uint16_t Kp; // pGain
uint16_t Ki; // iGain
uint16_t Kd; // dGain
// PID calculations OLD ONES WHERE STATICS
int24_t pTerm;
int32_t iTerm;
int32_t dTerm;
int32_t PID;
// Extra variabels
int16_t CurrentError;
// PID Time
uint16_t tick;
}_PIDObject;
In C source:
static int16_t PIDUpdate(int16_t target, int16_t feedback)
{
_PIDObject PID2_t;
PID2_t.Kp = pGain2; // Has the value of 2000
PID2_t.CurrentError = target - feedback; // Has the value of 57
PID2_t.pTerm = PID2_t.Kp * PID2_t.CurrentError; // Should count this to (57x2000) = 114000
What happens when I debug is that it don't. The largest value I can define (kind of) in pGain2 is 1140. 1140x57 gives 64980.
Somehow it feels like the program thinks PID2_t.pTerm is a uint16_t. But it's not; it's declared bigger in the struct.
Has PID2_t.pTerm somehow got the value uint16_t from the first declared variables in the struct or
is it something wrong with the calculations, I have a uint16_t times a int16_t? This won't happen if I declare them outside a struct.
Also, here is my int def (have never been a problem before:
#ifdef __18CXX
typedef signed char int8_t; // -128 -> 127 // Char & Signed Char
typedef unsigned char uint8_t; // 0 -> 255 // Unsigned Char
typedef signed short int int16_t; // -32768 -> 32767 // Int
typedef unsigned short int uint16_t; // 0 -> 65535 // Unsigned Int
typedef signed short long int int24_t; // -8388608 -> 8388607 // Short Long
typedef unsigned short long int uint24_t; // 0 -> 16777215 // Unsigned Short Long
typedef signed long int int32_t; // -2147483648 -> 2147483647 // Long
typedef unsigned long int uint32_t; // 0 -> 4294967295 // Unsigned Long
#else
# include <stdint.h>
#endif
Try
PID2_t.pTerm = ((int24_t) PID2_t.Kp) * ((int24_t)PID2_t.CurrentError);
Joachim's comment explains why this works. The compiler isn't promoting the multiplicands to int24_t before multiplying, so there's an overflow. If we manually promote using casts, there is no overflow.
My system doesn't have an int24_t, so as some comments have said, where is that coming from?
After Joachim's comment, I wrote up a short test:
#include <stdint.h>
#include <stdio.h>
int main() {
uint16_t a = 2000, b = 57;
uint16_t c = a * b;
printf("%x\n%x\n", a*b, c);
}
Output:
1bd50
bd50
So you're getting the first 2 bytes, consistent with an int16_t. So the problem does seem to be that your int24_t is not defined correctly.
As others have pointed out, your int24_t appears to be defined to be 16 bits. Beside the fact that it's too small, you should be careful with this type definition in general. stdint.h specifies the uint_Nt types to be exactly N bits. So assuming your processor and compiler don't actually have a 24-bit data type, you're breaking with the standard convention. If you're going to end up defining it as a 32-bit type, it'd be more reasonable to name it uint_least24_t, which follows the pattern of integer types that are at least big enough to hold N bits. The distinction is important because somebody might expect uint24_t to rollover above 16777215.