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
Related
I have a file called hittable.h that looks like this:
#ifndef HITTABLE_H
#define HITTABLE_H
#include "ray.h"
#include "vec3.h"
#include "material.h"
#include <stdbool.h>
typedef struct hit_record{
point3 p;
vec3 normal;
material* mat_ptr;
double t;
bool front_face;
} hit_record;
static inline void set_face_normal(hit_record *rec, const ray *r, vec3 outward_normal) {
rec->front_face = (dot(r->direction, outward_normal) < 0);
rec->normal = rec->front_face ? outward_normal : negate(outward_normal);
}
#endif
and I have another file called material.h that looks like this:
#ifndef MATERIAL_H
#define MATERIAL_H
#include "vec3.h"
#include "ray.h"
typedef struct {
color albedo;
} lambertian;
bool lambertian_scatter(lambertian lam, const ray* r_in, const hit_record* rec, color attenuation, ray* scattered) {
return false;
}
typedef struct{
int type;
union {
lambertian lam;
};
} material;
#endif
As you can see, in the the file material.h, the function lambertian_scatter()'s third argument is of type hit_record *. However, in hittable.h, the struct hit_record (which is required in material.h) has a member of type material which is defined in material.h. I tried several things and I couldn't fix this problem and was wondering what I should do.
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.
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
I have 2 header files api.h and impl.h
api.h is visible to outside files and will be included in other ".c" files. So api.h includes impl.h
api.h defines 2 structures
typedef struct
{
uint32_t att;
union
{
struct
{
void* buffer;
size_t length;
} x;
struct
{
int a, b;
} v;
} content;
}dummy;
and impl.h has some other structures and function def which uses this structure.
I tried forward declaration but it doesn't help me .
Please help .
Actually, your dummy is not a structure, but a typedef to an unnamed structure. Try naming the structure, you can then forward-declare it:
typedef struct sdummy dummy; // forward declaration
void foo(dummy *);
struct sdummy { ... }; // definition
Either reorder your code in api.h so the type declaration precedes the #include "impl.h" or give your (currently anonymous) structure itself a name like dummy, dummy_, dummy_s so you can add a forward declaration
typedef struct dummy_ dummy;
to impl.h.
If you want to hide the details of your struct then you have to define it in some .c file, let's say impl.c, so that it has internal linkage to that compilation unit. To use it you have to expose create, destroy, getter and setter functions. So a basic setup would look like this:
api.h with forward declaration for your struct
// forward declaration
typedef struct dummy* dummy_t;
// create / destroy / setter / getter (omitted)
dummy_t alloc_dummy();
void free_dummy(dummy_t);
void set_number(dummy_t, int);
void set_string(dummy_t, char*);
void print_dummy(dummy_t);
Then comes impl.c
#include "api.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct dummy {
int n;
char* s;
};
dummy_t alloc_dummy()
{
return malloc(sizeof(struct dummy));
}
void free_dummy(dummy_t dummy)
{
if(dummy) {
free(dummy->s);
free(dummy);
}
}
void set_number(dummy_t dummy, int n)
{
if(dummy) {
dummy->n = n;
}
}
void set_string(dummy_t dummy, char* s)
{
if(dummy && s) {
dummy->s = strdup(s);
}
}
void print_dummy(dummy_t dummy)
{
if(dummy) {
printf("%d, %s\n", dummy->n, dummy->s);
}
}
And finally the usage in some other C files, here main.c
#include "api.h"
int main(int argc, char** argv)
{
// struct dummy d; // error! type is unknown
// instead use the create function
dummy_t d = alloc_dummy();
// d->n = 1; // error! dereference of unknown type
// instead use the setter function
set_number(d, 1);
set_string(d, "Hello, world!");
print_dummy(d);
free_dummy(d);
return 0;
}
Ouput
1, Hello, world!
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.