Problems Initializing Structures - c

Here are (some of) the structures that I am using; they are in a .h file:
struct rss_s {
Radio_types device_type; // Its device_type which is defined by the typedef above Radio_Types
char * device_info; // some thing about the radio NAV/COM/etc.
char * device_model; // the Manufactures part/model number.
char * device_serial; // the device's serial number..
int power_48v; // power to the unit..
int power_400hz;
int panel_lamps; // turn off or on the Panel Lamps only
void * radio_info;
};
typedef struct tuner_s { // when we talk about 'sub-radios' we are really saying how many tuners are there??
char * device_name; // OS-name
int frequency[tuned];
int power;
int dial_lamp;
int fd[ ]; // file descriptors
}tuner;
//// 614L8 ::= C614L8
typedef enum Lp_Sw_614L8 { OFF_loop, LEFT, RIGHT, SLEW_LEFT, SLEW_RIGHT } loopsw_614L8;
typedef enum Mo_Sw_614L8 { OFF_614L8, ADF, ANT, LOOP } modesw_614L8;
struct radio_s_614L8 {
loopsw_614L8 loop_sw_614L8;
modesw_614L8 mode_sw_614l8;
int sw_band;
int sw_bfo;
int meter;
tuner * Tuner;
int tuners;
};
Now file main.c, which has all of the normal includes:
// Radio 614L8<br>
static struct radio_s_614L8 radio_614L8 = { { .Tuner = tuner_614L8, .tuners = DIM( tuner_C_614L8 ) } };
static tuner tuner_614L8 = { { .device_name = "/dev/TBD", } };
static struct rss_s radios[] = {
{ C614L8, "ADF", "614L8", "8384", & radio_C_614L8,},};
// now comes the normal main()
The errors that I have:
error: field name not in record or union initializer
error: (near initialization for ‘radio_614L8.loop_sw_614L8’)
error: ‘tuner_614L8’ undeclared here (not in a function)
error: field name not in record or union initializer
error: (near initialization for ‘radio_614L8.loop_sw_614L8’)
error: ‘tuner_C_614L8’ undeclared here (not in a function)
error: field name not in record or union initializer
error: (near initialization for‘tuner_614L8.device_name’)
error: ‘radio_C_614L8’ undeclared here (not in a function)

You currently have:
static struct radio_s_614L8 radio_614L8 = { { .Tuner = tuner_614L8, .tuners = DIM( tuner_C_614L8 ) } };
static tuner tuner_614L8 = { { .device_name = "/dev/TBD", } };
You need:
static tuner tuner_614L8 = { .device_name = "/dev/TBD", };
static struct radio_s_614L8 radio_614L8 = { .Tuner = &tuner_614L8, .tuners = 1 };
You can't refer to a variable like tuner_614L8 until you've defined or declared it. You shouldn't try to make a non-array into an array, either. You do need to take the address of the tuner, too. You don't show DIM, but I'm assuming it is more or less one of these two equivalent macros:
#define DIM(x) (sizeof(x)/sizeof(*(x)))
#define DIM(x) (sizeof(x)/sizeof((x)[0]))
On further analysis, your tuner structure contains a flexible array member. You can't sensibly allocate such variables as static or global variables, or as automatic variables; you have to allocate them with malloc() and relatives to get a non-empty array.
However, with that caveat in mind, this code compiles:
typedef enum Radio_types { C614L8 } Radio_types;
enum { tuned = 5 };
typedef struct tuner_s
{
char *device_name;
int frequency[tuned];
int power;
int dial_lamp;
int fd[];
} tuner;
typedef enum Lp_Sw_614L8 { OFF_loop, LEFT, RIGHT, SLEW_LEFT, SLEW_RIGHT } loopsw_614L8;
typedef enum Mo_Sw_614L8 { OFF_614L8, ADF, ANT, LOOP } modesw_614L8;
struct radio_s_614L8
{
loopsw_614L8 loop_sw_614L8;
modesw_614L8 mode_sw_614l8;
int sw_band;
int sw_bfo;
int meter;
tuner *Tuner;
int tuners;
};
static tuner tuner_614L8 = { .device_name = "/dev/TBD", };
static struct radio_s_614L8 radio_614L8 = { .Tuner = &tuner_614L8, .tuners = 1 };
struct rss_s
{
Radio_types device_type;
char *device_info;
char *device_model;
char *device_serial;
int power_48v;
int power_400hz;
int panel_lamps;
void *radio_info;
};
struct rss_s radios[] =
{
{ C614L8, "ADF", "614L8", "8384", 0, 0, 0, &radio_614L8, },
};

Related

Malloc and realloc for union of structs linked to array of structs

What's the best way to dinamically allocate memory to an array of structs with union included? I should malloc and then realloc to record_user or to data_user? Below I explain more of it, this is the sample code:
core.h
#define MAX_USER sizeof(record_user) / sizeof(record_user[0])
#define MAX_ARTIST sizeof(record_artist) / sizeof(record_artist[0])
/* all my other defines here */
typedef enum {
admin = 1,
basic = 0
} type;
typedef struct {
int hour;
int minute;
int second;
} tm;
typedef struct {
int day;
int month;
int year;
} date;
typedef struct {
short id;
char name[MAX_USER_NAME];
char surname[MAX_USER_SURNAME];
char email[MAX_USER_EMAIL];
char password[MAX_PASSWORD_LENGTH];
date birthday;
date subscription_date;
tm subscription_time;
type role;
} user;
typedef struct {
short id;
char name[MAX_ARTIST_NAME];
char genre[MAX_GENRE][MAX_GENRE_NAME];
char producer[MAX_PRODUCER_NAME];
char nationality[MAX_NATIONALITY_NAME];
int starting_year;
} artist;
/* and other structs */
typedef struct {
enum { USER, ARTIST } type;
union {
user *u_user;
artist *u_artist;
};
int size;
} data;
data.h
#ifndef DATA_H
#define DATA_H
#include "core.h"
extern user record_user[];
extern artist record_artist[];
extern data data_user;
extern data data_artist;
/* etc */
#endif
data.c
#include "data.h"
// SOME PRESET DATA
user record_user[] = {
{ 1, "Name 1", "Surname 1", "name1.surname1#email.com", ",+o[oS", { 29, 9, 1996 }, { 7, 3, 2011 }, { 18, 25, 58 }, 0 },
/** The list goes on **/
}
artist record_artist[] = {
{ 1, "Coldplay", { "Pop", "Britpop", "Alternative Rock" }, "Parlophone", "United Kingdom", 1997 },
/** The list goes on **/
}
data data_user = { .type = USER,.u_user = record_user,.size = MAX_USER };
data data_artist = { .type = ARTIST,.u_artist = record_artist,.size = MAX_ARTIST };
As you can see, there is a union struct for artist and user. I decided to create a union struct in order to pass multiple array of structs to a generic function. In the full code, I have more unions, but that's not the point to list them all. I just really need to understand what's I'm going to further explain below.
record_user like record_artist has some preset data that I link to data_user and data_artist respectively in data.c. Now this data needs to be increased during the runtime. I mean if record_user has 100 preset data rows (same thing for record_artist) in it, I'd like to add more rows or even remove them. For that I know there's malloc and realloc. I tried to play with it, making some tests and I don't know what's the best way of doing that.
I tried to declare in my main.c file the following:
int main() {
data_user.u_user = (user *)malloc(size * sizeof(user));
/***/
}
but I also tried with this
int main() {
record_user = (user *)malloc(size * sizeof(user));
/***/
}
but as I already imagined I lose all the preset data delcared in data.c file.
MY GOAL
What I'd like to achieve is to malloc a temp size for my data (for starting 100) and then to link the array of structs (or the union struct), with the starting temp size, to my preset data in order for using them. Naturally, during runtime, I will add more rows, and for that I'll use realloc (or even remove them).
This is the sample code of my add function:
data *add_data(data *record_data) {
date record_date;
tm record_time;
switch (record_data->type) {
case USER:
{
/* SOMEWHERE HERE I should use realloc to my record_data */
int ID = record_data->size;
record_data->u_user[ID].id = ID;
printf("\n\n\tNEW USER");
printf("\n\tEnter name: ");
strcpy(record_data->u_user[ID].name, inputString(MIN_USER_NAME, MAX_USER_NAME));
printf("\tEnter surname: ");
strcpy(record_data->u_user[ID].surname, inputString(MIN_USER_SURNAME, MAX_USER_SURNAME));
printf("\tEnter email: ");
strcpy(record_data->u_user[ID].email, inputString(MIN_USER_EMAIL, MAX_USER_EMAIL));
printf("\tEnter password: ");
strcpy(record_data->u_user[ID].password, inputString(MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH));
/* etc for birthday, subscription date */
record_data->size += 1;
printf("\n\tUser added!");
return record_data;
}
case ARTIST:
/* asking for input data */
return record_data;
}
}
this is how I call the function instead in the main.c file
int main() {
/***/
data_user = *add_data(&data_user);
/***/
}
I don't know how to move here, if I should work with the struct record_user or the union struct data_user. If it's the same or not... if I work with the original struct (allocating memory), is the union capable of reading the new memory size or not? Or is it best to work with the union struct leaving the original struct untouched?
I hope someone clear my mind!

How can an array of structs be initialized using a const struct in global scope?

I want to use code similar to the following (but a lot more complex - this is a simplified example) to initialize an array of structures, but during compilation I get the error "expression must have a constant value".
typedef struct
{
int x;
int y;
} windowStruct_t;
static const windowStruct_t windowStructInit =
{
.x = 3,
.y = 5,
};
// These get defined differently at times. This is simplified for the example.
#define NUM_ARRAY_ELEMENTS (2)
#define REPEAT_NUM_ARRAY_ELEMENTS_TIMES(x) (x),(x)
// The following line causes the error "expression must have a constant value" twice.
windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] =
{ REPEAT_NUM_ARRAY_ELEMENTS_TIMES( windowStructInit ) };
void someFunction( void )
{
volatile int x = windowStruct[0].x;
}
void anotherFunction( void )
{
volatile int y = windowStruct[1].y;
}
Manually expanding the macro and replacing the line that causes the error with the following gives the same result:
windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] =
{ windowStructInit, windowStructInit };
But this compiles without error:
windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] =
{ { .x = 3, .y = 5 }, { .x = 3, .y = 5 } };
If I move the array declaration inside of function scope, it compiles without errors (I am ignoring the fact that someFunction() and anotherFunction() now access different arrays and that their lifetimes are different):
void someFunction( void )
{
windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] =
{ REPEAT_NUM_ARRAY_ELEMENTS_TIMES( windowStructInit ) };
volatile int x = windowStruct[0].x;
}
void anotherFunction( void )
{
windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] =
{ REPEAT_NUM_ARRAY_ELEMENTS_TIMES( windowStructInit ) };
volatile int y = windowStruct[1].y;
}
Leaving the array declarations inside of function scope, if they are declared to be "static", the error message comes back:
void someFunction( void )
{
static windowStruct_t windowStruct[ NUM_ARRAY_ELEMENTS ] =
{ REPEAT_NUM_ARRAY_ELEMENTS_TIMES( windowStructInit ) };
volatile int x = windowStruct[0].x;
}
So it seems that when the arrays are declared as automatic variables (on the stack) that they can be initialized in a way that isn't allowed when the memory allocation is static (whether inside function scope or in global scope where the allocation is static even without the "static" keyword). Is there a way to initialize the array in global scope using a const struct as in the original example?
I am using C, not C++. I don't want to use dynamic memory allocation. The compiler is TI's ARM compiler V16.6.0.STS as included in their Code Composer Studio environment.
A const object is not a C constant. Instead use constants which is required for non-automatic storage objects.
Define an initializer { .x = 3, .y = 5 }
typedef struct windowStruct_s {
int x;
int y;
} windowStruct_t;
#define windowStruct_t_default_initializer { .x = 3, .y = 5 }
#define NUM_ARRAY_ELEMENTS (2)
#define REPEAT_NUM_ARRAY_ELEMENTS_TIMES(x) x, x /* no () */
windowStruct_t windowStruct[NUM_ARRAY_ELEMENTS] = {
REPEAT_NUM_ARRAY_ELEMENTS_TIMES(windowStruct_t_default_initializer) };
int someFunction(void) {
volatile int x = windowStruct[0].x;
return x;
}
int anotherFunction(void) {
volatile int y = windowStruct[1].y;
return y;
}

Create an array containing structs in C

I've been working on creating my own GUI library for MS-DOS on my free time and I got stuck on how I can implement an array that would contain structures of GUI elements.
So far I was able to make it draw the window itself, but I needed a way to draw the elements inside the window such as text boxes, text labels, buttons, ect.
Here's my current code:
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <string.h>
#include "graph.h" //Watcom graphics library
#define false 0
#define true 1
#define border_none 0
#define border_out 1
#define border_in 2
struct text_button {
char text[128];
int pos_x;
int pos_y;
int size_x;
int size_y;
int text_color;
int button_color;
};
struct window_structure {
char title[128];
int pos_x;
int pos_y;
int pre_pos_x;
int pre_pos_y;
int size_x;
int size_y;
int min_size_x;
int min_size_y;
int max_size_x;
int max_size_y;
int show_tab;
int border_type;
int focused;
//Right here is where I would add the array containing the elements.
};
void draw_border(int type,int pos_x,int pos_y,int size_x,int size_y) {
int c_1,c_2;
if (type==1) {
c_1=15;
c_2=0;
} else if (type==2) {
c_1=0;
c_2=15;
}
if (type!=0) {
_setcolor(c_1);
_moveto(pos_x,pos_y);
_lineto(pos_x+size_x,pos_y);
_moveto(pos_x,pos_y);
_lineto(pos_x,pos_y+size_y);
_setcolor(c_2);
_moveto(pos_x+size_x,pos_y+size_y);
_lineto(pos_x+size_x,pos_y);
_moveto(pos_x+size_x,pos_y+size_y);
_lineto(pos_x,pos_y+size_y);
}
}
void draw_box(int type,int color,int pos_x,int pos_y,int size_x,int size_y) {
_setcolor(color);
_rectangle(_GFILLINTERIOR,pos_x,pos_y,pos_x+size_x,pos_y+size_y);
draw_border(type,pos_x-1,pos_y-1,size_x+2,size_y+2);
}
struct window_structure create_window(
char title[],
int pos_x,
int pos_y,
int size_x,
int size_y,
int min_size_x,
int min_size_y,
int max_size_x,
int max_size_y,
int show_tab,
int border_type
) {
struct window_structure window;
strcpy(window.title,title);
window.pos_x=pos_x;
window.pos_y=pos_y;
window.pre_pos_x=pos_x;
window.pre_pos_y=pos_y;
window.size_x=size_x;
window.size_y=size_y;
window.min_size_x=min_size_x;
window.min_size_y=min_size_y;
window.max_size_x=max_size_x;
window.max_size_y=max_size_y;
window.show_tab=show_tab;
window.border_type=border_type;
window.focused=true;
return window;
}
void draw_window(struct window_structure window) {
int offset_x,offset_y;
if (window.size_x<window.min_size_x) {
window.size_x=window.min_size_x;
} else if (window.size_x>window.max_size_x) {
window.size_x=window.max_size_x;
}
if (window.size_y<window.min_size_y) {
window.size_y=window.min_size_y;
} else if (window.size_y>window.max_size_y) {
window.size_y=window.max_size_y;
}
if (window.show_tab==true) {
int tab_color;
if (window.focused==true) {
tab_color=9;
} else {
tab_color=8;
}
draw_box(
window.border_type,
tab_color,
window.pos_x,
window.pos_y-1,
window.size_x-1,
18
);
offset_x=0;
offset_y=20;
}
draw_box(
window.border_type,
7,
window.pos_x+offset_x,
window.pos_y+offset_y,
window.size_x-1,
window.size_y-1
);
//Once the window has been drawn, the next part it would do here is draw the elements
window.pre_pos_x=window.pos_x;
window.pre_pos_y=window.pos_y;
}
I know MS-DOS is quite outdated, this is just for my hobby. I'm currently using Open Watcom as my compiler.
//Right here is where I would add the array containing the elements.
You know, since you'll have a variable number of elements, you can't declare a fixed-size array here, so you can just declare a pointer and allocate the array as needed. You'll also need to store the number of elements allocated.
struct window_structure
{
…
int nelem; // how many elements are there
struct element *elements; // pointer to allocated elements
};
Both shall be initialized to 0.
struct window_structure create_window(…)
{
…
window.nelem = 0;
window.elements = NULL;
return window;
}
The struct element type could be defined as
struct element
{ enum elemtype { text_button, /* add other types here */ } elemtype;
union
{ struct text_button tb;
/* add other types here */
} u;
};
An element, e. g. a text_button, could then be added to the window with
struct element *new;
new = realloc(window.elements, (window.nelem+1) * sizeof *new);
if (!new) exit(1); // or some better error handling
window.elements = new;
window.elements[window.nelem].elemtype = text_button;
window.elements[window.nelem].u.tb = your_text_button_to_add;
++window.nelem;
//Once the window has been drawn, the next part it would do here is draw the elements
This would then be done like
int i;
for (i = 0; i < window.nelem; ++i)
switch (window.elements[i].elemtype)
{
case text_button:
/* draw the text_button window.elements[i].u.tb here */
break;
/* add cases for other element types here */
}

can't seem to locate the struct

I am trying to fetch values from a struct once its been updated however the problem am facing is an undeclared error as it cannot seem to see it.
sonicNav.h file
#include<stdio.h>
#include<stdlib.h>
#include"sonicThread.h"
extern void calcSonicS();
sonicThread.c file.
int funcLock = 0;
void calcSonicS() {
struct results *rData = results;
rData = malloc(sizeof(struct results));
int newVal1 = rData->sens1;
int newVal2 = rData->sens2;
int newVal3 = rData->sens3;
int newVal4 = rData->sens4;
if(funcLock == 0){
funcLock = threadFunc();//returns INT value of 1.
}
printf("value 1: %d value 2: %d value 3: %d value 4 %d\n", newVal1, newVal2, newVal3, newVal4);
}
sonicThread.h file
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<string.h>
#include<errno.h>
#include<pthread.h>
#include<sys/time.h>
#include<wiringPi.h>
//GPIO PINS stored within structs, for each sonic range finder.
typedef struct sonicPins{
//pins and id.
int trig;
int echo;
int id;
}args;
typedef struct results{
//all pins
int sens1;
int sens2;
int sens3;
int sens4;
}rData;
sonicThread.c file
void* setup(void *pinsPtr);
extern int threadFunc();
pthread_t pt[4];
int threadFunc()
{
struct sonicPins pinsArray[4] = { { 21, 20, 1 }, { 16, 12, 2 }, { 26, 19, 3 }, { 13, 6, 4 } };
for(int i =0; i <4; i++){
pthread_create(&pt[i], NULL, setup, &pinsArray[i] );
}
return 1;
}
void* setup(void *pinsPtr)
{
struct sonicPins *ptr = pinsPtr;
int trig = 0, Echo = 0, id;
trig = ptr->trig;
Echo = ptr->echo;
id = ptr->id;
struct results *storePtr;
}
The snippet above does update the struct "results", all threads does work concurrently each sensor giving out is own result.
Main.c
int main(){
//void(*foo1)(int, int, int);
//foo1 = &calcSonicS;
printf("In operation\n");
int operational = 1;
while(operational ==1)
{
//sonic range finders.
calcSonicS();
//gyroscope and acceometer.
}
return 0;
}
Error output:
sonicNav.c: In function ‘calcSonicS’:
sonicNav.c:5:28: error: ‘results’ undeclared (first use in this function)
sonicNav.c:5:28: note: each undeclared identifier is reported only once for each function it appears in
struct results *rData = results;
error: ‘results’ undeclared (first use in this function)
The above line tries to declare and define a local variable named rData, which has type struct results *, and initialise it with the value of the variable (local or global) results. The error message is telling you that there is no such variable.
What you're probably mixing up is C++ (old, bad) style initialisation:
MyClass variable = MyClass();
Since the next thing you do with rData is assigning it ...
rData = malloc(sizeof(struct results));
... the solution to your issue is to just remove that "wrong initialisation" from the preceeding line altogether. You could also pack it into a single line:
struct results *rData = malloc(sizeof(struct results));
Looking at ...
typedef struct results{
// ...
} rData;
... I'd guess that you have a serious misunderstanding of the relationship of structure (type) names, type names and variable names. The above definition gives you:
The name results as structure (type) name, so it can be used after struct to name the defined structure type.
The name rData as type name, referring to the same (structure) type as struct results.
When you then declare a variable struct results *rData you have additionally rData as name for a variable. This is possible, but far from good style.
If you remove the typedef, then things would change drastically: You'd then have a global variable named rData of type struct results.

structures and pointers error: dereferencing pointer to incomplete type

ok I have three structs:
struct rss_s {
Radio_types device_type; // Its device_type which is defined by the typedef above Radio_Types
char * device_info; // some thing about the radio NAV/COM/etc.
char * device_model; // the Manufactures part/model number.
char * device_serial; // the device's serial number..
int power_48v; // power to the unit..
int power_400hz;
int panel_lamps; // turn off or on the Panel Lamps only
void * radio_info;
struct radio_s_C614L8
{
loopsw_614L8 loop_sw_614L8; this is an emum
modesw_614L8 mode_sw_614L8; this is an emum
int sw_band;
int sw_bfo;
int meter;
tuner *Tuner;
int tuners;
};
typedef struct tuner_s
{
char *device_name; // OS NAME
int frequency[tuned];
int power;
int dial_lamp;
void * back_radio; // back-link to radios[n]
void * back_info; // back-link to radio_xxxx
int fd[];
} tuner;
I initialize them in main.c
// Radio 614L8
static tuner tuner_C614L8[] = {{ .device_name = "/dev/TBD", }};
static struct radio_s_C614L8 radio_C614L8 = { .Tuner = &tuner_C614L8, .tuners = DIM(tuner_C614L8) };
static struct rss_s radios[] = {
{ .device_type = C614L8,
.device_info = "ADF",
.device_model = "614L8",
.device_serial = "8384",
.radio_info = &radio_C614L8,},};
the above works with out errors....
but when I try to initialize the the above radio... in my init_C614L8.c
with the following code I get an error...
error: dereferencing pointer to incomplete type in lines 4 & 6
int init_C614L8( struct rss_s * radios ){
int rw, i;
struct radio_s_614L8 * rad_info = radios -> radio_info;
tuner * this_tuner = rad_info -> Tuner;
// Now we will loop over the sub_devices....
for ( i = 0; i < rad_info -> tuners; i++ ) {
I think I have to cast something but not shure
Thanks
In rss.h you declare
struct radio_s_C614L8
but in init_C614L8.c you use
struct radio_s_614L8
which is declared nowhere.
Update:
To fix this error
error: dereferencing pointer to incomplete type
In init_C614L8.c (and any other place, but rss.h) replace
struct radio_s_614L8
by
struct radio_s_C614L8
The lesson learned here is either go for some glasses or some sleep! ;-) And also: "The compiler never lies!"
This means that the definition of struct radio_s_614L8 is not visible to the code where the errors are seen. You have either forgotten to include the definition or there are #if... directives removing the definitions or includes you think are there.

Resources