Table in struct initialisation in C - c

How to initialise the table DetectionSensors in this structure:
typedef struct
{
DetectionSensor *DetectionSensors[];
unsigned char nbSensors;
} SENSOR_STRUCT;
SENSOR_STRUCT my_var = { } ?
This table contains just some DetectionSensor pointers;

You can't; the structure definition shown shouldn't compile.
typedef struct
{
DetectionSensor *DetectionSensors[]; // Not C
unsigned char nbSensors;
} SENSOR_STRUCT;
If you're trying for a flexible array member (FAM), that has to be the last field in the structure and you can't write initializers for structure containing a FAM.
Otherwise, you need to use an explicit size for the dimension of the array, or lose the array notation and use DetectionSensor *DetectionsSensors; (or conceivably, but it seems implausible) DetectionSensor **DetectionSensors;.
typedef struct
{
DetectionSensor *DetectionSensors[10]; // Use an enum or #define
unsigned char nbSensors;
} SENSOR_STRUCT;
With this, you need some DetectionSensors around:
DetectionSensor ds[10];
SENSOR_STRUCT my_var = { { &ds[0], &ds[1], &ds[2], &ds[3] }, 4 };
In general, reserve ALL_CAPS for macros (FILE and DIR notwithstanding).

If your intention is to initialise the structure with a predefined set of Detectionsensor, you can do like this.
DetectionSensor sample [] = {sensor1, sensor2];
my_var.DetectionSensors = sample;

There's no automatic constructor for C structs, first you need to build the DetectionSensors array and then assign the value of that array to the DetectionSensor variable in your SENSOR_STRUCT.
typedef struct
{
DetectionSensor * DetectionSensors;
unsigned char nbSensors;
} SENSOR_STRUCT;
DetectionSensor * sensors = ...; //get your detection sensors.
SENSOR_STRUCT my_var = {sensors, ... };

You should reserve some memory for the DetectionSensors, e.g. this way:
#define MAX_SENSORS 10
typedef struct
{
DetectionSensor *DetectionSensors[MAX_SENSORES];
unsigned char nbSensors;
} Sensor_Struct;
Sensor_Struct my_var;
myvar.DetectionSensors[0] = somePointer;
my_var.nbSensors = 1;
btw: CAPS_LOCKED_NAMES are by convention for preprocessor variables (#define SOMETHING abc)
You could provide functions to add a new sensor and even make the memory use dynamic, if you need that.

Related

C access enum from struct

My problem is that car_name_str could not be resolved. Why is it not callable and I want to keep the code structure?
I want to keep the structure as struct with union and enum (different datatypes).
Template: How can mixed data types (int, float, char, etc) be stored in an array?
//car_union.h
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex[30][3];
extern Car_data_ex *Car_data[30][3];
//fill_car.c
#include "car_union.h"
Car_data_ex *Car_data[30][3];
Car_data[0][0]->type = car_name_str; //-> because pointer but doesnt work
Car_data[0][0]->value->car_name= "land rover";
Car_data[0][1]->type = car_cost_float; //doesnt work
Car_data[0][1]->value->car_cost= 45000;
Just remove the [30][3] from the type def, like this
#include <stdio.h>
//car_union.h
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex;
extern Car_data_ex *Car_data[30][3];
int main() {
Car_data_ex *Car_data[30][3];
Car_data[0][0]->type = car_name_str; //-> because pointer but doesnt work
Car_data[0][0]->value.car_name= "land rover";
Car_data[0][1]->type = car_cost_float; //doesnt work
Car_data[0][1]->value.car_cost= 45000;
}
Regardless of what's in your struct, when you do
typedef struct Car_dataStructTag{
//...
}Car_data_ex[30][3];
(I've tagged the struct so it can be referred to by struct Car_dataStructTag),
then Car_data_ex is a type alias resolving to struct Car_dataStructTag [30][3]
which means
extern Car_data_ex *Car_data[30][3];
is fully equivalent to
extern struct Car_dataStructTag (*Car_data[30][3])[30][3];
which means Car_data[x][y] is a pointer to a two-dimensional array of struct Car_dataStructTag,
which is definitely not something you can apply -> to.
Try:
typedef struct Car_dataStructTag{
//...
}Car_data_ex[30][3];
extern Car_data_ex *Car_data[30][3];
extern struct Car_dataStructTag (*Car_data[30][3])[30][3];
in a compiler -- it gets accepted, confirming the declaration equivalence.
Running into situations such as this one is why it's generally considered ill-advisable to typedef arrays or pointers.
You have over complexified everything.
A typedef is just to give an alias to a (complex) type. Here the type is a struct containing an enum and an union. So it should be:
typedef struct {
enum { number_of_seats_int, car_cost_float, car_name_str } type;
union {
int number_of_seats;
float car_cost;
char* car_name;
} value;
}Car_data_ex;
Next, using an array of pointers can make sense, but provided each pointer in the array does point to a true object. Here you only want a plain (2D) array:
Car_data_ex Car_data[30][3];
Once this has been done, you can write with no error or warning:
Car_data[0][0].type = car_name_str;
Car_data[0][0].value.car_name= "land rover";
Car_data[0][1].type = car_cost_float;
Car_data[0][1].value.car_cost= 45000;
And you should avoid extern Car_data_ex Car_data[30][3];. It declares a global array, that will have to be defined in one single compilation unit (.c file). Here again, it can make sense, but IMHO it is a rather advanced feature that can be hard to correctly use. And nothing in the shown code lets think that is is required...

How to initialize the array fields of a struct with zeroes

I have a the following struct
typedef struct mainstruct {
uint32_t var1;
field_struct var2[2];
uint32_t var3;
} main_struct;
where field_struct is :
typedef struct fieldstruct {
uint8_t var11[8];
uint32_t var22;
uint32_t var33;
uint8_t var44[16];
uint8_t var55[16];
uint8_t var66[16];
} field_struct;
How can I initialize all the field_struct field in main_struct to all zeroes ?
Also var1 and var2 need to be initialized to specific values.
If you partially initialize the struct, the rest of the members that you don't initialize explicitly are set to zero. So it is enough to just initialize those members that need specific values:
main_struct ms =
{
.var1 = something,
.var2 = { something_else },
};
How can I initialize all the field_struct field in main_struct to all zeroes?
If you don't have access to designated initializers (C99 and C11), you can simply zero-initialize the entire struct and then initialize the rest to whatever you need:
main_struct s = {0};
s.var1 = ...;
The optimizer will do the right thing. Of course, if you don't want to initialize everything, you would have to manually initialize the ones you need only.
If you're trying to set default values for struct members then you simply can't do it: structures are data types, not instances of data types.
Instead, if you only want to initialize the members of an instance of your data type then you can use the method described in Lundin's answer.

How to declare array of structs in C

I am having trouble declaring an array of structs prior to populating them with data.
My struct looks like this:
typedef struct {
uint8_t * p_data; ///< Pointer to the buffer holding the data.
uint8_t length; ///< Number of bytes to transfer.
uint8_t operation; ///< Device address combined with transfer direction.
uint8_t flags; ///< Transfer flags (see #ref NRF_TWI_MNGR_NO_STOP).
} nrf_twi_mngr_transfer_t;
And in my code I am trying to declare the array like this:
struct nrf_twi_mngr_transfer_t start_read_transfer[10];
However I get a compile error:
array type has incomplete element type 'struct nrf_twi_mngr_transfer_t'
I have searched around as I thought should be a common thing, but I can't figure out what I am doing wrong. Maybe because one of the elements is a pointer? But that pointer should be a fixed size right?
Many thanks
It looks like some explanations are in order. This code
typedef struct {
//...
} nrf_twi_mngr_transfer_t;
Already defines a type which can be used directly. In contrast,
struct nrf_twi_mngr_transfer_struct {
//...
};
Would define a struct name, and to access it you'd need to indicate that you are referring to a struct.
As a result, given two definitions above, you should define your arrays differently:
nrf_twi_mngr_transfer_t arr[10]; // if using typedef
struct nrf_twi_mngr_transfer_struct arr2[10]; // if using struct with no typedef
And just in case you are wondering,
struct {
//...
} nrf_twi_mngr_transfer_obj;
Defines an object of anonymous struct type.

Allocating memory and filling the structure elements of a structure

I have defined the structure in a separate header file and I have included that header file in my main file.
The header file consists of a structure like this:
typedef struct
{
char name[32];
unsigned int a;
unsigned int b;
NUMBER_ONE variable1;
NUMBER_TWO variable2;
}NUMBER_THREE,*PNUMBER_THREE;
typedef struct
{
unsigned int variable3;
char variable4[8];
}NUMBER_ONE,*PNUMBER_ONE;
typedef struct
{
unsigned int variable5;
char variable6[8];
}NUMBER_TWO,*PNUMBER_TWO;
Now in my main file I have to allocate memory for this structure and I need to fill this structure with some values, so anybody please tell me how to do this. I need to send this through socket client to the socket server.
If you have written it in that order you present it, then the code should not even compile since the first typedef has no clue on what NUMBER_ONE or NUMBER_TWO types are.
To allocate it should just be to define a variable of given type.
int main()
{
NUMBER_TWO number_two_var;
number_two_var.variable5 = 10;
}
I would also recommend using a postfix for each typdef, for example NUMBER_TWO_T.
Edit: Postfix being _T
In C a struct is initialized by an initializer
NUMBER_TWO a2 = { .variable5 = 7, .variable6 = { 'a', }, };
the form I am giving here are so-called designated initializers that came starting with C99. Oldish C had only the equivalent
NUMBER_TWO a2 = { 7, { 'a' } };
where you have to specify the values in declaration order.
For both forms, fields that are omitted from the initializer are initialized with 0.

Using structure in C and C++

I am new to C and I want to know how to access elements inside a structure which is placed inside a structure.
struct profile_t
{
unsigned char length;
unsigned char type;
unsigned char *data;
};
typedef struct profile_datagram_t
{
unsigned char src[4];
unsigned char dst[4];
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
} header;
How to access elements inside profile_t??
struct profile_t;
The above statement doesn't create an object of type profile_t. What you need to do is -
struct profile_t inObj ;
Then create object for profile_datagram_t. i.e.,
header outObj ; // header typedef for profile_datagram_t
Now you can access elements like -
outObj.inObj.type = 'a' ; // As an example
In C++, while creation of object for a structure, struct key word isn't necessary.
On your question edit and comment :
struct profile_t profiles[MAXPROFILES];
profiles is an array of objects of type profile_t. To access the individual object, just use the [] operator. i.e.,
header obj ;
obj.profiles[0].type = 'a' ; // Example
obj.profiles[i], where i can take values from 0 to MAXPROFILES - 1, gives the object at index i.
Not sure what happends in C, but in C++, rest of the stuff aside, the following declares two types.
struct profile_datagram_t
{
struct profile_t;
};
One type is named profile_datagram_t and the other is called profile_datagram_t::profile_t. The inner type declaration is just a forward declaration, so you'll need to define the type after.
struct profile_datagram_t::profile_t
{
// ...
};
Then, you can use the struct as follows:
int main ( int, char ** )
{
profile_datagram_t::profile_t profile;
}
Some compilers support a nonstandard extension to the C language (that I actually rather like, despite it being nonstandard) called anonymous structs (or unions). Code demonstration:
struct x {
int i;
};
struct y {
struct x;
};
int main(void)
{
struct y;
y.i = 1; // this accesses member i of the struct x nested in struct y
return 0;
}
In a nutshell, if you don't give the struct (or union) member a name, you can access its members directly from the containing struct (or union). This is useful in situations where you might have given it the name _, and had to do y._.i - the anonymous struct syntax is much simpler. However, it does mean that you have to remember the names of all members of both structs and ensure they never clash.
This is all, of course, a nonstandard extension, and should be used with caution. I believe it works on MSVC and can be enabled in GCC with a switch. Don't know about any other compilers. If you're worried about portability, give the member a proper name.
EDIT: According to the GCC reference (below) this behavior is being added to the upcoming C1X standard, so it won't be nonstandard for long. I doubt MSVC will support C1X since they refuse to support C99 as it is, but at least this feature is becoming part of the standard.
However, the behavior shown above is MSVC only. The C1X (and GCC without the -fms-extensions switch) syntax doesn't allow the unnamed struct member to have a name:
struct y {
struct {
int i;
};
};
int main(void) {
struct y;
y.i = 1; // this accesses member i of the struct x nested in struct y
return 0;
}
References for various compilers (they have different names but are the same concept):
GCC (unnamed fields): http://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html'
MSVC (anonymous structs): http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx
Basically you can use the following format:
variable = profile_t.element
profile_t.element = ?
EDIT: In your declaration of profile_datagram_t, the proper definition for struct profile_t should be:
struct profile_t someProfile;
Let's say you have:
header profileDiagram1;
struct profile_t profile1;
profileDiagram1.someProfile = profile1;
To access length, type or *data from profile_t:
profileDiagram1.someProfile.type;
profileDiagram1.someProfile.length;
...

Resources