I tried to use bit fields in a struct for some values which only need one or two bits instead of a whole byte.
My code is:
struct s_rdata {
signed int p0:28;
signed int p1:28;
signed int p2:28;
unsigned int d0:17;
unsigned int d1:17;
unsigned int d2:17;
unsigned char data1:1;
unsigned char data2:1;
} rdata;
So, you might see that there are variables named p0 - p2, d0 - d2 and data1 - data2.
I'd now like to have those in an array. However, none of this lines does work:
signed int p[3]:28;
signed int p:28[3];
Can't I add an array to a bitfield list, an array of signed int only needing 28 bits per entry?
No, you cannot have an array of bitfields, nor a bitfield whose base type is an array type. The latter doesn't even make sense. The former would be counter-productive, as you would lose any space efficiency gained by using bitfields in the first place.
You can have an array of a structs with a single bitfield member:
struct container {
signed int bitfield:7;
} array[3];
but again, you would lose any space efficiency associated with the bitfield use.
You can create an array of any struct type, of course, including those with multiple bitfield members. In that case, you may achieve some internal space efficiency within the individual structures, but you will likely see padding at the end of each one that reduces the overall space efficiency of the array.
Ultimately, unless your program's memory consumption is excessive for its target environment, I strongly recommend that you forget about bitfields. They will complicate your life for an uncertain gain of uncertain importance, and that gain will likely be offset by a performance degradation (of uncertain magnitude and importance).
Should you eventually decide that the program really is using too much memory, then be certain to test any change you make to see how much improvement it yields, and at what cost.
I agree with #John's assessment with respect to space inefficiencies, but that notwithstanding, here is an idea to contain contents of a bit field within struct array:
typedef struct
{
int A : 16;
int B : 16;
} Struct1;
typedef struct
{
Struct1 B;//bitfield struct
int array[10];//combined with array (of any legal type)
}
Here is an example of populating array with contents of bit struct:
typedef struct {
signed int p0:28;
signed int p1:28;
signed int p2:28;
unsigned int d0:17;
unsigned int d1:17;
unsigned int d2:17;
unsigned char data1:1;
unsigned char data2:1;
} RDATA;
typedef struct {
int A[3];
unsigned int B[3];
unsigned char C[2];
} ARRAY;
RDATA rdata = {//initialize instance of RDATA with data
28,
28,
28,
17,
17,
17,
1,
1
};
int WriteToArray(ARRAY *a);
int main(void)
{
ARRAY a;
WriteToArray(&a);//populate array with RDATA values
//ARRAY is now populated with bitfield values;
a.A[0];
a.A[1];
//and so on
return 0;
}
WriteToArray(ARRAY *a)
{
a->A[0]=rdata.p0;//using values initialized above
a->A[1]=rdata.p1;
a->A[2]=rdata.p2;
a->B[0]=rdata.d0;
a->B[1]=rdata.d1;
a->B[2]=rdata.d2;
a->C[0]=rdata.data1;
a->C[1]=rdata.data2;
return 0;
}
You can also experiment with pragma pack statements to look at effects on space, but refer to #John's comment under your post for additional considerations regarding pragma and spacing.
Related
I was trying to find the answer of a question which involves two structures inside a union.
I have typed the question in online debugger the answer which I am finding and the real answer is not giving hands to each other. Can somebody help me out with the answer with explanation.
#include <stdio.h>
int main()
{
union{
struct{
char c[2];
char ch[2];
}s;
struct {
short int i;
short int j;
}st;
}u={12,1,15,1};
printf("%d%d",u.st.i,u.st.j);
}
answer is 268 and 271
Decimal numbers are not very good for this kind of tests. You should also enable all warnings as well. If you do so you will get
<source>:25:8: warning: missing braces around initializer [-Wmissing-braces]
So let's rewrite your program a little bit:
int main()
{
union
{
struct
{
char c[2];
char ch[2];
}s;
struct
{
short int i;
short int j;
}st;
}u={.s = {{0x12,0x01},{0x15,0x01}}}; //better to show compiler what you want to initialize
printf("%04hx %04hx",u.st.i,u.st.j);
}
And the result is:
0112 0115
clearly showing the numbers we have used in the initialization. The numbers show us that this system uses little endian system where the least significant byte is placed first.
You should be avare that compiler is free to add any padding needed. To avoid it you have to use compiler extensions - structure packing.
Start by making more sense of this by swapping to hexadecimal: {0xC,0x1,0xF,0x1}. This allows us to view the bytes as they are stored in memory, without worrying about converting to/from decimal base.
When initializing a union, the first member gets initialized, in this case the struct s.
It would be cleaner to write { {{0xC,0x1}, {0xF,0x1}} } but unfortunately C allows omitting the curly braces of inner structs/arrays, allowing us to put sloppily written crap in our initialization lists just because we can.
The memory order of a char byte array is always top to bottom on any system: first byte on least significant address. That is: 0xC 0x1 0xF 0x1.
Strictly speaking, the compiler is free to add struct padding bytes anywhere between the struct/union members, to compensate for misalignment. Doesn't happen in this specific case, but it would happen if we for example used char c[3].
When you "type pun" this memory area using shorts, they get read according to endianess, since short is larger than 1 byte and an integer type.
On a little endian CPU you would therefore get each short to assume that 0xC is the least significant byte and so the first short ends up as 010C hex.
If we translate your code to hex, it should be clearer:
#include <stdio.h>
int main()
{
union{
struct{
char c[2];
char ch[2];
}s;
struct {
short int i;
short int j;
}st;
}u={ {{0xC,0x1}, {0xF,0x1}} };
printf("%.4X\n%.4X",u.st.i,u.st.j);
}
Output on little endian CPU:
010C
010F
10Ch = 268d and so on.
I am a bit confused with the output of the following code although I know what the declaration of such struct means in C.
#include<stdio.h>
struct struc
{
int a:1;
int b:3;
int c:6;
int d:3;
}s1;
struct stru
{
char a:3;
}s2;
int main()
{
printf("%lu %lu",sizeof(s1),sizeof(s2));
getchar();
return 0;
}
I am trying to learn the actual working of this type of structure declaration.
Can anyone explain how the code is giving output as "4 1", as I want to get the grasp over the concept properly.
And also the following code:
#include <stdio.h>
struct marks{
int p:3;
int c:3;
int m:2;
};
int main(void) {
struct marks s={2,-6,5};
printf("%d %d %d",s.p,s.c,s.m);
return 0;
}
What should be the output from this program?
The code you show is using bit fields. In a nutshell, :n after a struct member restricts this member to use only n bits, and such members are "packed" together when adjacent members have the same type.
A long time ago, this was sometimes useful to save memory -- nowadays, you might need it in very low-level hardware interfacing code, but that's probably about it.
What happens here:
struct struc
{
int a:1;
int b:3;
int c:6;
int d:3;
}s1;
This struct only has 1 + 3 + 6 + 3 = 13 bits worth of information. Assuming your implementation uses 32 bit int and a char has 8 bits, the sizeof int is 4 (32 / 8), and this is still enough to store all the bits of your members here. So the size of the whole struct is still only 4.
Note that all of this is implementation defined -- it depends on the sizes of char and int and the compiler is still free to add padding as needed. So using bitfields requires you to know what exactly your implementation is doing, at least if you need to rely on sizes and the exact layout of the bits.
In the example we can see that the 1st struct uses int and the 2nd struct uses a char.
The char gives a size result of 1. Which I think is as expected.
If we look at the sizes of variables :
cpp reference - types
Then we can see that an int can take up 16 or 32 bits.
As size of your struct is 4 we can determine that your compiler uses 32 bits for this storage.
I have two different structures and and two const look up tables as below
typedef const struct
{
unsigned int num;
unsigned char name[100];
unsigned int value1;
unsigned int value2;
unsigned int value3;
}st_Table1;
typedef const struct
{
unsigned int num;
unsigned char name[100];
}st_Table2;
st_Table1 stTable1[] =
{
{ 1, "Name1", 12, 13, 14 },
{ 2, "Name2", 22, 23, 24 },
{ 3, "Name3", 32, 33, 34 },
{ 4, "Name4", 42, 43, 44 }
};
st_Table2 stTable2[] =
{ 1, "India1" },
{ 2, "India2" },
{ 3, "India3" }
};
Could it be possible to have single pointer that can point to both the lookup tables stTable1 and stTable2?
When I have to make the decision for selection of either of the two tables we can assign the address of the table (either of).
But after that I wanted to use the single pointer in the remaining code.
Please reply for any logic ... hint ... clue
Arvind
well you could create a struct
typedef struct _tableChoice
{
st_Table1* table1;
st_Table2* table2;
} tableChoice_t,*p_tableChoice_t;
then you could pass along an argument of type p_tableChoice_t until you need to specifically access one of the tables. If you need to decide during runtime what pointer to use you would need to have both pointers available at the decision point.
You can get the same effect as the casts other have suggested with a union as well
union table_ptr {
st_Table1*table1;
st_Table2*table2;
} my_table_ptr;
and just assign/access the desired member.
You could create a void pointer:
void * ptr;
Like any other pointer this can point to any memory address but it doesn't specify what type of data is stored there, so you could dereference it but you'd have to depend on your own knowledge of the structures to access different elements etc.. If you have some other flag indicating what type of record it's pointing to, you could cast it back to the required type of pointer.
Given that both of your structs have common ground you'd be better off just using the first one and accepting the small overhead on memory for instances where you only need num and name. I hate software bloat and wasted memory, but you're talking about an extra 12 bytes (on most platforms) for records where value1-3 are not needed, so unless we're talking about billions of records chances are the extra code required to deal with more will consume more memory than the wasted space.
Another option could be a union, where you lose 12 bytes from name for records of the second type so that all records take up the same amount of space, though of course compiler padding my make a difference on some platforms.
You may want to follow a similar pattern to the sockaddr family of structures. In that setup, all of the structures must have the same size and the same initial layout, something like:
typedef const struct
{
unsigned int num;
unsigned char name[100];
char buffer_[sizeof(unsigned int) * 3];
} st_TableBase;
typedef const struct
{
unsigned int num;
unsigned char name[100];
unsigned int value1;
unsigned int value2;
unsigned int value3;
} st_Table1;
typedef const struct
{
unsigned int num;
unsigned char name[100];
char buffer_[sizeof(unsigned int) * 3];
} st_Table2;
With this structure, you would normally maintain a pointer of type st_TableBase. With this pointer you'll be able to access the num or name members directly, since all of the types have a consistent initial layout. If you need to access additional fields, you can cast st_TableBase to one of the "derived" types.
For more information on the sockaddr structures see http://www.retran.com/beej/sockaddr_inman.html.
It's impossible. A pointer must know its own range in order to read and write correctly during runtime, or you can do nothing with it. If you don't know whether it's table1 or table2, how can you write code to read it? (what type is the value in value = *pointer; ?) On the other hand, if you do know it's a table1/table2, why not use a pointer of specific type?
OR (if you insist)
Just use st_Table1 as st_Table2 and accept the waste of memory (3*sizeof(unsigned int) for each record). It won't be a big waste unless you have billions of record. You don't want to hold billions of data record by C structure.
OR (well, you hate waste)
typedef struct
{
int num;
char name[100];
int *value;
}st_table;
well, you have a unified structure now. Allocate value during runtime if you need it (value = (int *)malloc(3 * sizeof(int));). Don't forget the NULL check before you read value.
I read a bunch of input(sensors) where I get 0(off) or 1(on) for every sensor. These values I get in a char* where I have the result for all sensors. 1 bit for every sensor.
When I want to use these values in my code I don't feel like it is a good idea to AND this result with another char with the one bit set which i'm interested in since the code gets very bloated then.
Instead i was thinking of to make a struct like this one:
struct sensors {
unsigned int Sensor0:1;
unsigned int Sensor1:1;
unsigned int Sensor2:1;
unsigned int Sensor3:1;
unsigned int Sensor4:1;
unsigned int Sensor5:1;
unsigned int Sensor6:1;
unsigned int Sensor7:1;
}
struct sensors s1;
memcpy(buf, (char*)&sensors, 1);
But from what I've read a struct might not save every component after each other in memory and might insert padding and other stuff in between which makes this a no go.
Am I wrong about this? Are there any better ways to do this?
With your current definition of struct sensors, the compiler will insert additional padding because int has alignment requirements, usually on a sizeof(int) boundary. Moreover, int must be wider than char, hence it can accommodate more than 8 flags, which you're not gonna need.
If you declare it like this (use unsigned char instead), there should be no padding because char has the least strict alignment requirements:
struct sensors {
unsigned char Sensor0:1;
unsigned char Sensor1:1;
unsigned char Sensor2:1;
unsigned char Sensor3:1;
unsigned char Sensor4:1;
unsigned char Sensor5:1;
unsigned char Sensor6:1;
unsigned char Sensor7:1;
}
This might not work only on a very strange platform where CHAR_BIT != 8.
To add to Blagovest's answer:
A bit-field approach seems sound. However, you'll have to instruct your compiler to not introduce a padding between the fields. For GCC, this is done by putting __attribute__ ((packed)) after the definition of a structure, like this:
struct sensors {
unsigned char Sensor0:1;
unsigned char Sensor1:1;
unsigned char Sensor2:1;
unsigned char Sensor3:1;
unsigned char Sensor4:1;
unsigned char Sensor5:1;
unsigned char Sensor6:1;
unsigned char Sensor7:1;
} __attribute__ ((packed));
Note that GCC before 4.4 used to introduce padding for char fields irrespective of this directive; see the documentation on warning option -Wpacked-bitfield-compat for more information.
If you want to be super-safe, you can AND with a character that has one bit set. You probably would want to do this with an array, instead of a struct. You can wrap it into a nice loop, and it's not much work at all.
However, any sane C compiler will put unsigned integers in contiguous memory, so it should be safe to do some kind of copy like that. The compiler usually only puts in extra padding when there are types of different sizes. Unfortunately I do not know if this will work easily for you because you have the command memcpy(buf, (char*)&sensors, 1) will copy your byte of sensor data in the first integer - which is not what you want.
Instead of memcpy(), I would use a union to access the data as defined in Blagovest Buyukliev answer:
union combSensors {
unsigned char all_fields;
struct sensors field_by_field;
}
I am attempting to learn more about C and its arcane hidden powers, and I attempted to make a sample struct containing a pointer to a void, intended to use as array.
EDIT: Important note: This is for raw C code.
Let's say I have this struct.
typedef struct mystruct {
unsigned char foo;
unsigned int max;
enum data_t type;
void* data;
} mystruct;
I want data to hold max of either unsigned chars, unsigned short ints, and unsigned long ints, the data_t enum contains
values for those 3 cases.
enum Grid_t {gi8, gi16, gi32}; //For 8, 16 and 32 bit uints.
Then I have this function that initializes and allocates one of this structs, and is supposed to return a pointer to the new struct.
mystruct* new(unsigned char foo, unsigned int bar, long value) {
mystruct* new;
new = malloc(sizeof(mystruct)); //Allocate space for the struct.
assert(new != NULL);
new->foo = foo;
new->max = bar;
int i;
switch(type){
case gi8: default:
new->data = (unsigned char *)calloc(new->max, sizeof(unsigned char));
assert(new->data != NULL);
for(i = 0; i < new->max; i++){
*((unsigned char*)new->data + i) = (unsigned char)value;
//Can I do anything with the format new->data[n]? I can't seem
//to use the [] shortcut to point to members in this case!
}
break;
}
return new;
}
The compiler returns no warnings, but I am not too sure about this method. Is it a legitimate way to use pointers?
Is there a better way©?
I missed calling it. like mystruct* P; P = new(0,50,1024);
Unions are interesting but not what I wanted. Since I will have to approach every specific case individually anyway, casting seems as good as an union. I specifically wanted to have much larger 8-bit arrays than 32-bits arrays, so an union doesn't seem to help. For that I'd make it just an array of longs :P
No, you cannot dereference a void* pointer, it is forbidden by the C language standard. You have to cast it to a concrete pointer type before doing so.
As an alternative, depending on your needs, you can also use a union in your structure instead of a void*:
typedef struct mystruct {
unsigned char foo;
unsigned int max;
enum data_t type;
union {
unsigned char *uc;
unsigned short *us;
unsigned int *ui;
} data;
} mystruct;
At any given time, only one of data.uc, data.us, or data.ui is valid, as they all occupy the same space in memory. Then, you can use the appropriate member to get at your data array without having to cast from void*.
What about
typedef struct mystruct
{
unsigned char foo;
unsigned int max;
enum data_t type;
union
{
unsigned char *chars;
unsigned short *shortints;
unsigned long *longints;
};
} mystruct;
That way, there is no need to cast at all. Just use data_t to determine which of the pointers you want to access.
Is type supposed to be an argument to the function? (Don't name this function or any variable new or any C++ programmer who tries to use it will hunt you down)
If you want to use array indices, you can use a temporary pointer like this:
unsigned char *cdata = (unsigned char *)new->data;
cdata[i] = value;
I don't really see a problem with your approach. If you expect a particular size (which I think you do given the name gi8 etc.) I would suggest including stdint.h and using the typedefs uint8_t, uint16_t, and uint32_t.
A pointer is merely an address in the memory space. You can choose to interpret it however you wish. Review union for more information on how you can interpret the same memory location in multiple ways.
casting between pointer types is common in C and C++, and the use of void* implies that you dont want users to accidentally dereference (dereferencing a void* will cause an error, but dereferencing the same pointer when cast to int* will not)