I have a struct defined as:
typedef struct {
uint8_t field1 : 6,
uint8_t field2 : 1,
uint8_t field3 : 1
} myStruct;
and then:
myStruct s;
What is a safe way to assign an 8-bit value to all the fields at once, i.e.:
s = 10;
The compiler gives error when trying to assign like this (obviously, I'm not even implying this is the way to do it :) ).
Would this be recommended:
uint8_t a = 10;
s = * ((myStruct*) &a);
?
You can use a union:
union myUnion {
struct myStruct ms;
uint8_t byte;
};
myUnion u;
u.byte = 10; /* Uses the same memory as myStruct and its fields. */
printf("field1=%u field2=%u field3=%u\n", u.ms.field1, u.ms.field2, u.ms.field3);
This used to be frowned upon, but see #mafso's comment below, it seems to be allowed now.
you can't assign values to the structure elements like this-
myStruct s;
s = 10;
It is Not allowed. It is not a correct way to do the things!
When you do like below-
uint8_t a = 10;
s = * ((myStruct*) &a);
It is not a safe way to allocate the value 10 to the bit field members! So do it individually like-
s.field1=xx; // Instead of xx, yy and zz assign values
s.field2=yy;
s.field3=zz;
It is the best way to do it!
Related
I have a struct that looks something like this:
typedef struct
{
uint32_t a;
uint32_t b;
uint32_t c[5];
uint32_t d;
} MY_STRUCT_T;
I want to initialize c, by name, to a non-zero value. I want everything else to be 0.
If c were not an array, I could do:
static MY_STRUCT_T my_struct = {.b = 1};
And I know I can do this:
static MY_STRUCT_T my_struct = {.c[0]=5,
.c[1]=5,
.c[2]=5,
.c[3]=5,
.c[4]=5};
but I was wondering if there was a more elegant syntax of which I am unaware:
Something like:
static MY_STRUCT_T my_struct = {.c[] = {5,5,5,5,5}};
I have read the following, but they don't answer this question:
Initializing a struct to 0
Initialize/reset struct to zero/null
A better way to initialize a static array member of a class in C++ ( const would be preferred though )
How to initialize all members of an array to the same value?
So I wrote this question and then experimented for a while and found that the following would work:
static MY_STRUCT_T my_struct = {.c={5,5,5,5,5}};
OP has 3 goals: 1) field array size is fixed width, 2) initialization like {7,7,7,7,7} is fixed width, 3) c to a non-zero value. As #1 and #2 have their sizes independent coded, 2 of the 3 goals can be met, but not all 3 - that is tricky.
What is to prevent/warn about MY_STRUCT_T my_struct = {.c = {5,5,5,5,5}}; not meeting goals should uint32_t c[5]; later become uint32_t c[6];? Nothing really.
Lacking a maintainable coding paradigm, consider this - copy one by one
I have two structures as follows
typedef struct Rsp_s {
u8 code;
u8 Count;
}Rsp_t;
typedef struct Field_s {
u8 State;
u8 present;
u8 previous;
u8 event;
} Field_t
Then i have
Rsp_t *rsp;
Field_t data[3][7]
I want data[0][0] to follow rsp->Count.
How do i do that?
data = (Field_t *)(&(rsp->Count) +1);
does not do it.
When you declare a variable like this ...
int b[3][7];
... its memory location is assigned by the compiler if static or given memory from the stack if automatic, and therefore cannot be changed programatically. You can however access this memory, and read to and write from it, by using a pointer ...
int (*a)[7] = b;
The following are equivalent:
b[0][0] = b[1][1];
a[0][0] = a[1][1];
Your assignment is the wrong way round. You want to assign to a the address of b[0][0], so:
a = &b[0][0];
let's say we have a union:
typedef union someunion {
int a;
double b;
} myunion;
Is it possible to check what type is in union after I set e.g. a=123?
My approach is to add this union to some structure and set uniontype to 1 when it's int and 2 when it's double.
typedef struct somestruct {
int uniontype
myunion numbers;
} mystruct;
Is there any better solution?
Is there any better solution?
No, the solution that you showed is the best (and the only) one. unions are pretty simplistic - they do not "track" what you've assigned to what. All they do is let you reuse the same memory range for all their members. They do not provide anything else beyond that, so enclosing them in a struct and using a "type" field for tracking is precisely the correct thing to do.
C does not automatically keep track of which field in a union is currently in use. (In fact, I believe reading from the "wrong" field results in implementation defined behavior.) As such, it is up to your code to keep track of which one is currently used / filled out.
Your approach to keeping a separate 'uniontype' variable is a very common approach to this, and should work well.
There is no way to directly query the type currently stored in a union.
The only ways to know the type stored in a union are to have an explicit flag (as in your mystruct example), or to ensure that control only flows to certain parts of the code when the union has a known active element.
Depending on the application, if it is a short lived object you may be able to encode the type in the control flow, ie. have separate blocks/functions for both cases
struct value {
const char *name;
myunion u;
};
void throwBall(Ball* ball)
{
...
struct value v;
v.name = "Ball"; v.u.b = 1.2;
process_value_double(&v); //double
struct value v2;
v2.name = "Age";
v2.u.a = 19;
check_if_can_drive(&v2); //int
...
}
void countOranges()
{
struct value v;
v.name = "counter";
v.u.a = ORANGE;
count_objects(&v); //int
}
Warning: the following is just for learning purpose:
You could use some ugly tricks to do so (as long as the data types in your union have different sizes, which is the present case):
#include <stdio.h>
typedef union someunion {
int a;
double b;
} myunion;
typedef struct somestruct {
int uniontype;
myunion numbers;
} mystruct;
#define UPDATE_CONTENT(container, value) if ( \
((sizeof(value) == sizeof(double)) \
? (container.uniontype = ((container.numbers.b = value), 2)) \
: (container.uniontype = ((container.numbers.a = value), 1))))
int main()
{
mystruct my_container;
UPDATE_CONTENT(my_container, 42);
printf("%d\n", my_container.uniontype);
UPDATE_CONTENT(my_container, 37.1);
printf("%d\n", my_container.uniontype);
return (0);
}
But I advise you never do this.
Maybe my variant is helping
struct Table
{
char mas[10];
int width;
int high;
union stat
{
int st;
char v;
} un;
};
Table tble[2];
strcpy(tble[0].mas, "box");
tble[0].high = 12;
tble[0].width = 14;
tble[0].un.v = 'S';
strcpy(tble[1].mas, "bag");
tble[1].high = 12;
tble[1].width = 14;
tble[1].un.st = 40;
//struct Table *ptbl = &tble[0];
//ptbl++;
for (int i = 0; i < 2; i++)
{
void *pt = &tble[i].un;
if(*((char*)pt) == 'S')
sort(put_on_bag_line);
else
sort(put_on_box_line);
}
typedef struct {
unsigned char a,
unsigned char b,
unsigned char c
}type_a;
typedef struct {
unsigned char e,
unsigned char f[2]
}type_b;
type_a sample;
sample.a = 1;
sample.b = 2;
sample.c = 3;
How do I typecast it and assign new value like:
sample = (type_b)sample; // syntax error
sample.f[1] = 'a';
You should really try it out yourself.
sample = (type_b)sample; /* Can't cast a structure to
another structure. */
sample.f[1] = 'a'; /* sample is still of type type_a,
and doesn't have an `f` field. */
No - C types are static, which means that sample will always remain of type type_a. However, you can achieve what you want using unions:
union {
type_a as_a;
type_b as_b;
} sample;
sample.as_a.a = 1;
sample.as_a.b = 2;
sample.as_a.c = 3;
sample.as_b.f[1] = 'a';
Note that it is not usual to create an object that is a bare union type like this; normally you would include the union within a struct, that includes a tag so that you know what type the object is at the present time:
struct {
enum { TYPE_A, TYPE_B } type;
union {
type_a as_a;
type_b as_b;
} data;
} sample;
/* sample is a TYPE_A right now */
sample.type = TYPE_A;
sample.data.as_a.a = 1;
sample.data.as_a.b = 2;
sample.data.as_a.c = 3;
/* sample is now a TYPE_B */
sample.type = TYPE_B;
sample.data.as_b.f[1] = 'a';
You can't cast one data type to another incompatible data type. However, the memory is open for you. You can access it as follows:
typedef struct
{
unsigned char a;
unsigned char b;
unsigned char c;
}type_a;
typedef struct
{
unsigned char e;
unsigned char f[2];
}type_b;
type_a sample;
sample.a = 1;
sample.b = 2;
sample.c = 3;
type_b *sample_b = (type_b *) ((void*) &sample);
Try out yourself accessing sample_b->e and sample_b->f and see what happens.
No. You can do it by casting pointers: value_b = *((value_b*)&value_a) or by creating union of those two types.
However you do it, be careful. Structures can have different data alignment and you may get unexpected results.
yes you can copy the value of the type_a into type_b by trying something like
type_b sample_b =*((type_b*)&sample);
or
memcpy(&sample_b,&sample,sizeof(type_a));
Typecasting is nothing but converting an expression of one type to another one. But you seem to be trying to convert the type itself, which is fixed at compile time(variable declaration)
Its not clear the idea behind trying something like this. If you can make it more clear, people would be able to give more insights
Is there an easy explanation for what this error means?
request for member '*******' in something not a structure or union
I've encountered it several times in the time that I've been learning C, but I haven't got a clue as to what it means.
It also happens if you're trying to access an instance when you have a pointer, and vice versa:
struct foo
{
int x, y, z;
};
struct foo a, *b = &a;
b.x = 12; /* This will generate the error, should be b->x or (*b).x */
As pointed out in a comment, this can be made excruciating if someone goes and typedefs a pointer, i.e. includes the * in a typedef, like so:
typedef struct foo* Foo;
Because then you get code that looks like it's dealing with instances, when in fact it's dealing with pointers:
Foo a_foo = get_a_brand_new_foo();
a_foo->field = FANTASTIC_VALUE;
Note how the above looks as if it should be written a_foo.field, but that would fail since Foo is a pointer to struct. I strongly recommend against typedef:ed pointers in C. Pointers are important, don't hide your asterisks. Let them shine.
You are trying to access a member of a structure, but in something that is not a structure. For example:
struct {
int a;
int b;
} foo;
int fum;
fum.d = 5;
It may also happen in the following case:
eg. if we consider the push function of a stack:
typedef struct stack
{
int a[20];
int head;
}stack;
void push(stack **s)
{
int data;
printf("Enter data:");
scanf("%d",&(*s->a[++*s->head])); /* this is where the error is*/
}
main()
{
stack *s;
s=(stack *)calloc(1,sizeof(stack));
s->head=-1;
push(&s);
return 0;
}
The error is in the push function and in the commented line. The pointer s has to be included within the parentheses. The correct code:
scanf("%d",&( (*s)->a[++(*s)->head]));
I have enumerated possibly all cases where this error may occur in code and its comments below. Please add to it, if you come across more cases.
#include<stdio.h>
#include<malloc.h>
typedef struct AStruct TypedefedStruct;
struct AStruct
{
int member;
};
void main()
{
/* Case 1
============================================================================
Use (->) operator to access structure member with structure pointer, instead
of dot (.) operator.
*/
struct AStruct *aStructObjPtr = (struct AStruct *)malloc(sizeof(struct AStruct));
//aStructObjPtr.member = 1; //Error: request for member ‘member’ in something not
//a structure or union.
//It should be as below.
aStructObjPtr->member = 1;
printf("%d",aStructObjPtr->member); //1
/* Case 2
============================================================================
We can use dot (.) operator with struct variable to access its members, but
not with with struct pointer. But we have to ensure we dont forget to wrap
pointer variable inside brackets.
*/
//*aStructObjPtr.member = 2; //Error, should be as below.
(*aStructObjPtr).member = 2;
printf("%d",(*aStructObjPtr).member); //2
/* Case 3
=============================================================================
Use (->) operator to access structure member with typedefed structure pointer,
instead of dot (.) operator.
*/
TypedefedStruct *typedefStructObjPtr = (TypedefedStruct *)malloc(sizeof(TypedefedStruct));
//typedefStructObjPtr.member=3; //Error, should be as below.
typedefStructObjPtr->member=3;
printf("%d",typedefStructObjPtr->member); //3
/* Case 4
============================================================================
We can use dot (.) operator with struct variable to access its members, but
not with with struct pointer. But we have to ensure we dont forget to wrap
pointer variable inside brackets.
*/
//*typedefStructObjPtr.member = 4; //Error, should be as below.
(*typedefStructObjPtr).member=4;
printf("%d",(*typedefStructObjPtr).member); //4
/* Case 5
============================================================================
We have to be extra carefull when dealing with pointer to pointers to
ensure that we follow all above rules.
We need to be double carefull while putting brackets around pointers.
*/
//5.1. Access via struct_ptrptr and ->
struct AStruct **aStructObjPtrPtr = &aStructObjPtr;
//*aStructObjPtrPtr->member = 5; //Error, should be as below.
(*aStructObjPtrPtr)->member = 5;
printf("%d",(*aStructObjPtrPtr)->member); //5
//5.2. Access via struct_ptrptr and .
//**aStructObjPtrPtr.member = 6; //Error, should be as below.
(**aStructObjPtrPtr).member = 6;
printf("%d",(**aStructObjPtrPtr).member); //6
//5.3. Access via typedefed_strct_ptrptr and ->
TypedefedStruct **typedefStructObjPtrPtr = &typedefStructObjPtr;
//*typedefStructObjPtrPtr->member = 7; //Error, should be as below.
(*typedefStructObjPtrPtr)->member = 7;
printf("%d",(*typedefStructObjPtrPtr)->member); //7
//5.4. Access via typedefed_strct_ptrptr and .
//**typedefStructObjPtrPtr->member = 8; //Error, should be as below.
(**typedefStructObjPtrPtr).member = 8;
printf("%d",(**typedefStructObjPtrPtr).member); //8
//5.5. All cases 5.1 to 5.4 will fail if you include incorrect number of *
// Below are examples of such usage of incorrect number *, correspnding
// to int values assigned to them
//(aStructObjPtrPtr)->member = 5; //Error
//(*aStructObjPtrPtr).member = 6; //Error
//(typedefStructObjPtrPtr)->member = 7; //Error
//(*typedefStructObjPtrPtr).member = 8; //Error
}
The underlying ideas are straight:
Use . with structure variable. (Cases 2 and 4)
Use -> with pointer to structure. (Cases 1 and 3)
If you reach structure variable or pointer to structure variable by following pointer, then wrap the pointer inside bracket: (*ptr). and (*ptr)-> vs *ptr. and *ptr-> (All cases except case 1)
If you are reaching by following pointers, ensure you have correctly reached pointer to struct or struct whichever is desired. (Case 5, especially 5.5)
It may means that you forgot include a header file that define this struct/union.
For example:
foo.h file:
typedef union
{
struct
{
uint8_t FIFO_BYTES_AVAILABLE : 4;
uint8_t STATE : 3;
uint8_t CHIP_RDY : 1;
};
uint8_t status;
} RF_CHIP_STATUS_t;
RF_CHIP_STATUS_t getStatus();
main.c file:
.
.
.
if (getStatus().CHIP_RDY) /* This will generate the error, you must add the #include "foo.h" */
.
.
.
can also appear if:
struct foo { int x, int y, int z }foo;
foo.x=12
instead of
struct foo { int x; int y; int z; }foo;
foo.x=12
I saw this when I was trying to access the members.
My struct was this:
struct test {
int a;
int b;
};
struct test testvar;
Normally we access structure members as
testvar.a;
testvar.b;
I mistook testvar to be a pointer and did this.
testvar->a;
That's when I saw this error.
request for member ‘a’ in something not a structure or union
My ridiculous experience is that I incorrectly put '.' instead of ','.
printf("%c". ch);