Static array initialization with pointer to extern struct element? - c

I want to statically initialize an array, but some of its element are pointer to extern struct.
I can't declare the struct as constant, as their element are modified elsewhere, neither static as it clash with extern declaration.
Is there a way to solve this in the static array initialization, or i have to initialize it in a function?
EDIT:
looking at your examples after a great launch I just found the error was i was using PWMD2 instead of &PWMD2 (where PWMD2 is the external struct).
Obviously the error was
error: initializer element is not constant
Just to point out what i am doing, the partial of the code (using ChibiOS) is the following:
esc.h
extern struct Engine{
GPIO_TypeDef *gpio;
uint8_t pin;
PWMDriver *driver;
pwmchannel_t channel;
pwmcnt_t width;
}engines[];
esc.c
struct Engine engines[] = {
{GPIOD, 3, &PWMD2, 0, 0},
{GPIOD, 4, &PWMD2, 1, 0},
{GPIOD, 6, &PWMD2, 2, 0},
{GPIOD, 7, &PWMD2, 3, 0},
};

Elaborate on your problem, because the following works ok for me and is what you're asking to do as far as I can tell:
main.c
#include <stdio.h>
#include "externs.h"
static struct_int_t* initextint[1] = { &extint };
int main( int argc, char* argv[] )
{
printf( "extint: %d\n", initextint[0]->value );
return 0;
}
externs.h
#ifndef EXTERNS_H
#define EXTERNS_H
typedef struct {
int value;
} struct_int_t;
extern struct_int_t extint;
#endif
externs.c
#include "externs.h"
struct_int_t extint = { 10 };
compile:
C:\>gcc main.c externs.c
run:
C:\>a
extint: 10

The following should work for example. What errors are you getting? What compiler and platform are you on? (You could remove consts as appropriate -- they're not essential.)
struct.h:
typedef struct My_struct {
int n;
} My_struct;
extern const My_struct s1, s2;
struct.c:
#include "struct.h"
const My_struct s1 = { 1 }, s2 = { 2 };
arr.c:
#include <stdio.h>
#include "struct.h"
static const My_struct *const arr[2] = { &s1, &s2 };
int main(void) {
printf("arr[0]->n = %d, arr[1]->n = %d\n", arr[0]->n, arr[1]->n);
return 0;
}
Compile with e.g.
$ gcc arr.c struct.c -o struct_arr

Related

C: Why do I get the compile error "dereferencing pointer to incomplete type ‘struct xy’"? [duplicate]

This question already has answers here:
C programming: Dereferencing pointer to incomplete type error
(6 answers)
Closed 3 years ago.
I have the problem described in the headline above. These are my files and their code:
run.c:
[...] // I think it's not relevant for the problem
declarations.h:
#ifndef DECLARATIONS_H
#define DECLARATIONS_H
#include <stdint.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
[...]
struct
{
int position;
int currentNumberOfMessages;
int numberOfProcesses;
char buf[MAX_PAYLOAD_LENGTH * MAX_SLOTS];
} mySharedMemory_sct = {0, 0, 0, '0'};
struct mySharedMemory_sct *myShMem_ptr;
[...]
#endif //DECLARATIONS_H
lib.h:
#ifndef LIB_H
#define LIB_H
#include "declarations.h"
#include <stdint.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
[...]
int init (int *argc, char **argv[])
{
/**
* map the shared memory into the process
*/
if ((myShMem_ptr = mmap(NULL, sizeof(mySharedMemory_sct), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==
MAP_FAILED)
{
printf("Error: %s\n", strerror(errno));
return EXIT_FAILURE;
}
/**
* increment the number of running processes called by the 'run'-process
*/
myShMem_ptr->numberOfProcesses += 1; <------- ERROR
[...]
return EXIT_SUCCESS;
}
[...]
#endif //LIB_H
For the line marked 'error' the compiler throws this error message:
"dereferencing pointer to incomplete type ‘struct mySharedMemory_sct’"
and highlights the '->' in "myShMem_ptr->numberOfProcesses += 1;" red as the problem.
I've read the other posts to this error message, but the problem causes were different (i think), so I haven't found a solution yet.
In advance: Thank you for your help!
You need to change
struct
{
int position;
int currentNumberOfMessages;
int numberOfProcesses;
char buf[MAX_PAYLOAD_LENGTH * MAX_SLOTS];
} mySharedMemory_sct = {0, 0, 0, '0'};
to
struct mySharedMemory_sct
{
int position;
int currentNumberOfMessages;
int numberOfProcesses;
char buf[MAX_PAYLOAD_LENGTH * MAX_SLOTS];
} mySharedMemory_sct = {0, 0, 0, '0'};
Let's have a look at a simpler case:
struct a {
int x;
} b;
So what do we have here? We have declared a struct and given it the name a, so this makes it possible to declare instances of that struct with struct a <name>. What about b? Well, that is an example of such an instance.
So what does this mean?
struct a {
int x;
} b = {0};
Well, it does certainly NOT mean that when you create an instance of struct a that the instance will have its x value initialized to 0. It only means that this is true for the very instance b.
You have not posted the complete code, but I suspect that this might do what you want:
struct mySharedMemory_sct {
int position;
int currentNumberOfMessages;
int numberOfProcesses;
char buf[MAX_PAYLOAD_LENGTH * MAX_SLOTS];
} mySharedMemory_sct = {0, 0, 0, '0'};
struct mySharedMemory_sct *myShMem_ptr = &mySharedMemory_sct;
An important thing to remember here is that mySharedMemory_sct and struct mySharedMemory_sct are two completely different things. mySharedMemory_sct is a variable with type struct mySharedMemory_sct. You can change their names independently of each other.

Circular header dependency

I am stuck on (what i think is) a circular dependency problem in VS2017 coding in c.
I tried looking up the problem, and found a lot of similar problems on stackoverflow, but I can't seem to get my problem solved with those questions.
My code:
main.c
#include <stdio.h>
#include "travelers.h"
#include "trip.h"
int main(void) {
int nTravelers = 0;
int nTrips = 0;
Traveler *travelersArray = (Traveler*)calloc(nTravelers, sizeof(Traveler));
Trip *tripsArray = (Trip*)calloc(nTrips, sizeof(Trip));
return 0;
}
travelers.h
typedef struct {
unsigned int id;
char *name;
char *adress;
char *residence;
} Traveler;
trip.h
typedef struct {
unsigned int id;
char *touringCar;
char *destination;
char *date;
Traveler *travelers;
unsigned int amount;
} Trip;
the travelers.c and trip.c files are only contain #include "travelers.h"/#include "trip.h"
The error occurs only in trip.h at Traveler *travelers;:
I don't know how to resolve this.
This looks like the same problem, but I couldnt translate it to my code.
Any help is apriciated.
No cycles here.
If trip.c includes trip.h is shall also include travelers.h as its definitions (Trip) depends on the latter (Traveller).
Knowing this, one could include travelers.h into trip.h. Still, this complicates things, so it is a good idea to 1st of all add to every header so call header-guards, protecting against duplicate definitions on pre-processor level.
Doing so made the headers look like this:
travelers.h
#ifndef TRAVELERS_H
#define TRAVELERS_H
typedef struct {
unsigned int id;
char *name;
char *adress;
char *residence;
} Traveler;
#endif // #ifndef TRAVELERS_H
trip.h
#ifndef TRIP_H
#define TRIP_H
#include "travelers.h" // makes including it unnecessary where trip.h is included
typedef struct {
unsigned int id;
char *touringCar;
char *destination;
char *date;
Traveler *travelers;
unsigned int amount;
} Trip;
#endif // #ifndef TRIP_H
As a remark, the error is caused by the typedef. C accepts opaque structs provided you do not need their implementation details:
a.h:
struct A {
int aVal;
const char * astr;
};
a.c:
#include "a.h"
const char *getAStr(struct A*a) {
return a->astr;
}
b.h
const char *getName(struct B*);
struct B {
int bVal;
struct A *a;
};
b.c
#include "b.h"
const char *getAStr(struct A*);
const char * getName(struct B* b) {
return getAStr(b->a);
}
main.c
#include <stdio.h>
#include "a.h"
#include "b.h"
int main() {
struct A a = { 1, "foo" };
struct B b = { 2, &a };
printf("%d - %d : %s\n", b.bVal, b.a->aVal, getName(&b));
return 0;
}
compiles and links without even a warning while in b.c nothing is known on struct A except that it is a struct.

c struct in multiple file error: dereferencing pointer to incomplete type

I am trying to declare a struct and use it in multiple files and I am getting an error that I cannot figure out. Sample code is posted below.
in test.h
#ifndef TEST_H
#define TEST_H
struct mystruct;
struct mystruct *new_mystruct();
void myprint(struct mystruct*,int);
#endif
int test.c
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
struct mystruct {
int *myarray;
};
struct mystruct *new_mystruct(int length)
{
int i;
struct mystruct *s;
s = malloc(sizeof(struct mystruct));
s->myarray = malloc(length*sizeof(int));
for(i = 0; i < length; ++i)
s->myarray = 2*i;
return s;
}
in main.c
#include "test.h"
#include <stdio.h>
int main()
{
int len = 10;
struct mystruct *c = new_mystruct(len);
myprint(c, len);
printf("%f", c->myarray[3]); // error: dereferencing pointer to incomplete type
return 0;
myprint() prints out 0 2 4 6 8 10 12 14 16 18. why doesn't the myprint(function work but the printf statement doesn't? why is it ok to pass it into a function but not use it in main? Thanks.
Currently main() only knows that struct mystruct is a type, but it doesn't know anything about its internal structure, because you've hidden it in test.c.
So you need to move this definition:
struct mystruct {
int *myarray;
};
from test.c to test.h, so that it's visible to main().
Note: what you're doing here is a classic example of an opaque type. This can be a very useful technique when you want to hide implementation details from code that is going to be calling your API.
Main.c doesn't know the contents of the mystruct structure. Try moving these lines:
struct mystruct {
int *myarray;
};
from test.c to test.h.
While you're at it, I think you mean "int myarray" not "int *myarray".

Visual Studio C2085 on Array Definition

In a .h file I have an extern declare:
extern const some_struct SomeArray[];
In the .c file I have the definition:
const some_struct SomeArray[] =
{
1, 2, 3, 4, 5 etc.
};
VS Express 2013 is complaining with a C2085, 'not in formal parameter list', which according to MSDN, means a function prototype wasn't declared before the definition, but this isn't a function, so I'm a bit lost...
Edit: More detail...
An entire .h:
#ifndef MYHEADER_H_
#define MYHEADER_H_
#include <stdint.h>
typedef uint32_t my_event;
typedef uint32_t my_state;
typedef my_event(*my_handler)(my_event, void *);
typedef struct my_table
{
my_event Event;
my_handler Handler;
my_state NextState;
} my_table;
#endif
and it's .c(pp):
#include "myheader.h"
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
typedef enum TestEnum
{
A,
B,
C,
} TestEnum;
my_event functionA(my_event E, void *pointer);
my_event functionB(my_event E, void *pointer);
const my_table TestArray[] =
{
A, functionA, A,
};
return 0;
}
this is an example of how to initialize an array of structs:
typedef struct { int a; char b; } A;
const A arr[] = {
{ 3, 'a' },
{ 7, 't' }
};
if that does not help you, show us a complete compilable
minimal example that exhibits the error

Initializing a Struct of a Struct

If I have a struct in C that has an integer and an array, how do I initialize the integer to 0 and the first element of the array to 0, if the struct is a member another struct so that for every instance of the other struct the integer and the array has those initialized values?
Initialisers can be nested for nested structs, e.g.
typedef struct {
int j;
} Foo;
typedef struct {
int i;
Foo f;
} Bar;
Bar b = { 0, { 0 } };
I hope this sample program helps....
#include <stdio.h>
typedef struct
{
int a;
int b[10];
}xx;
typedef struct
{
xx x1;
char b;
}yy;
int main()
{
yy zz = {{0, {1,2,3}}, 'A'};
printf("\n %d %d %d %c\n", zz.x1.a, zz.x1.b[0], zz.x1.b[1], zz.b);
return 0;
}
yy zz = {{0, {0}}, 'A'}; will initialize all the elements of array b[10] will be set to 0.
Like #unwind suggestion, In C all instances created should initialized manually. No constructor kind of mechanism here.
You can 0-initialize the whole struct with {0}.
For example:
typedef struct {
char myStr[5];
} Foo;
typedef struct {
Foo f;
} Bar;
Bar b = {0}; // this line initializes all members of b to 0, including all characters in myStr.
C doesn't have constructors, so unless you are using an initializer expression in every case, i.e. write something like
my_big_struct = { { 0, 0 } };
to initialize the inner structure, you're going to have to add a function and make sure it's called in all cases where the structure is "instantiated":
my_big_struct a;
init_inner_struct(&a.inner_struct);
Here is an alternative example how you would do things like this with object-oriented design. Please note that this example uses runtime initialization.
mystruct.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct mystruct_t mystruct_t; // "opaque" type
const mystruct_t* mystruct_construct (void);
void mystruct_print (const mystruct_t* my);
void mystruct_destruct (const mystruct_t* my);
#endif
mystruct.c
#include "mystruct.h"
#include <stdlib.h>
#include <stdio.h>
struct mystruct_t // implementation of opaque type
{
int x; // private variable
int y; // private variable
};
const mystruct_t* mystruct_construct (void)
{
mystruct_t* my = malloc(sizeof(mystruct_t));
if(my == NULL)
{
; // error handling needs to be implemented
}
my->x = 1;
my->y = 2;
return my;
}
void mystruct_print (const mystruct_t* my)
{
printf("%d %d\n", my->x, my->y);
}
void mystruct_destruct (const mystruct_t* my)
{
free( (void*)my );
}
main.c
int main (void)
{
const mystruct_t* x = mystruct_construct();
mystruct_print(x);
mystruct_destruct(x);
return 0;
}
You don't necessarily need to use malloc, you can use a private, statically allocated memory pool as well.

Resources