I cannot manage to solve the error, even though I've used these types of structures in other project in the same manner and it worked.
Meanwhile I'm not getting an errors in the declaration or initialisation of my structures.
The idea is to read information about a bunch of cars from a binary file.
It tells me that "struct Car" is an incomplete type and not allowed.
Here's the code I've made so far:
car.c
#include <stdio.h>
#include <string.h>
#include "car.h"
#define MAX_NUMBER_OF_CARS 10
struct Car importedCars[MAX_NUMBER_OF_CARS];
struct Config importedConfigs[MAX_NUMBER_OF_CARS];
int main( int argc, char* argv[]){
FILE *fp;
fp = fopen("cars.bin","rb");
if(fp != NULL)
{
fread(importedCars,sizeof(struct Car),MAX_NUMBER_OF_CARS,fp);
printf("1. Binary File read, structures of cars created.\n\n");
for(int i = 0; i < MAX_NUMBER_OF_CARS; i++)
{
printf("%s\t%s\t%s\t%d\t%f\t%f\t%f\t%d\n", importedCars[i].make, importedCars[i].model, importedCars[i].configuration.fuelType, importedCars[i].power, importedCars[i].torque, importedCars[i].fuelConsumption, importedCars[i].co2PerKm, importedCars[i].price);
}
}
else
{
printf("cannot read file.\n");
}
fclose(fp);
return 0;
}
car.h
#ifndef _CAR_H_
#define _CAR_H_
#define fuelLength 10
#define gearLength 10
#define conditionLength 10
#define makeLength 30
#define modelLength 30
typedef struct {
char fuelType[fuelLength];
char gearType[gearLength];
int numGears;
char condition[conditionLength];
} Config;
typedef struct {
char make[makeLength];
char model[modelLength];
Config configuration;
short power;
float torque;
float fuelConsumption;
float co2PerKm;
int price;
} Car;
I'm trying to experiment with opaque data types to get an understanding of them. The main problem is that I keep getting an 'incomplete' error.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "blepz.h"
int main()
{
setfnarp(GOO,5);
int loogaboo = getfnarp(GOO);
printf("%i", loogaboo);
return 0;
}
fnarpishnoop.c
#include "blepz.h"
struct noobza {
int fnarp;
};
void setfnarp(struct noobza x, int i){
x.fnarp = i;
};
int getfnarp(struct noobza x){
return x.fnarp;
};
blepz.h
struct noobza;
void setfnarp(struct noobza x, int i);
int getfnarp(struct noobza x);
struct noobza GOO;
I clearly don't understand something here and I was hoping someone could help me figure out how opaque data types are implemented if the whole point of them is that you have a hard time finding actual code for them.
Using a struct that you haven't declared the contents of gives an "incomplete type" error, as you have already mentioned.
Instead, use a pointer to the struct and a function that returns a pointer to the struct, like this:
struct noobza;
struct noobza *create_noobza(void);
void setfnarp(struct noobza *x, int i);
int getfnarp(struct noobza *x);
struct noobza *GOO;
...
#include <stdlib.h>
#include "blepz.h"
struct noobza {
int fnarp;
};
struct noobza *create_noobza(void)
{
return calloc(1, sizeof(struct noobza));
}
void setfnarp(struct noobza *x, int i){
x->fnarp = i;
};
int getfnarp(struct noobza *x){
return x->fnarp;
};
...
#include <stdio.h>
#include <stdlib.h>
#include "blepz.h"
int main()
{
GOO = create_noobza();
setfnarp(GOO,5);
int loogaboo = getfnarp(GOO);
printf("%i", loogaboo);
return 0;
}
Im trying to use the power of function pointers, it all went fine until i tried to make the function pointer use a 2nd argument as type int.
The code below generates an error, which is displayed below
In an header file:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
Error:
error: expected ‘)’ before ‘int’
void (*move)(Unit, int);
^
void (*move)(Unit); works all fine, which surprises me how adding an argument can cause an error.
I call my struct in a C file, by including header and then doing:
Unit units[UNITCOUNT];
units[0].move(&units[0], 1);
Update:
adding:
typedef struct UnitTag Unit
Causes the error to dissapear, however I can no longer use the function as before.
error: incompatible type for argument 1 of ‘units[i].move’
units[0].move(&units[0], 0);
^
note: expected ‘Unit’ but argument is of type ‘struct UnitTag *’
If I'm getting you, you can simply use struct keyword:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag, int);
} Unit;
void Test (struct UnitTag test1, int test2)
{
printf("Test1.x: %d\n", test1.x);
printf("Test1.y: %d\n", test1.y);
printf("Test2 : %d\n", test2);
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(units[0], 3);
}
Output:
Test1.x: 1
Test1.y: 2
Test2 : 3
If you want to pass struct by referebce, simply:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag*, int);
} Unit;
void Test (struct UnitTag *test1, int test2)
{
test1->x = 4;
test1->y = 5;
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(&units[0], 3);
printf("units[0].x: %d\n", units[0].x);
printf("units[0].y: %d\n", units[0].y);
}
Output is:
units[0].x: 4
units[0].y: 5
You need the prototype for Unit before using it.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
int main(void)
{
return 0;
}
After the clarification what you wanted to do. It probably makes more sense to give a pointer to Unit, so that the move command which returns void can change something about your object.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit *, int);
} Unit;
Unit test;
/* some function that corresponds to the interface */
void myMove(Unit *u, int i)
{
u->x = u->x + i;
}
int main(void)
{
/* initialize test struct */
test.x = 0;
test.y = 0;
test.move = myMove;
test.move(&test, 5);
printf("Values after move are (x, y) = (%i, %i).\n", test.x, test.y);
return 0;
}
When I try to compile a C file under 64-bit Linux using command:
gcc -o strain_from_faults_new strain_from_faults_new.c gen.h eqf.h
I met the following errors:
eqf.h:16:3: error: unknown type name ‘Point’
Point loc;
^
eqf.h:32:3: error: unknown type name ‘Point’
Point p[33];
^
eqf.h:44:3: error: unknown type name ‘Point’
Point p[33];
^
eqf.h:61:3: error: unknown type name ‘Point’
Point xy[NSEG];
^
It seems that type 'Point' is not defined, but it does defined in the file
gen.h
struct point {
double x;
double y;
};
typedef struct point Point;
I don't know why it have such an error, since this C file can be compiled in other computers. Is this 32bit-64bit compatible issue?
Any comment(s) would be highly appreciated!
According to the comments I #include "gen.h" in eqf.h file, but it not doing well. Since the two head files gen.h eqf.h have already been included in the C file strain_from_faults_new.c, the compiler have errors:
In file included from eqf.h:12:0,
from strain_from_faults_new.c:6:
gen.h:11:8: error: redefinition of ‘struct point’
struct point {
^
In file included from strain_from_faults_new.c:5:0:
gen.h:11:8: note: originally defined here
struct point {
^
Does anybody have any ideas?
Well, following are the entire codes:
gen.h
#define MAX_NAME 50
#define MAXNAME 50
#define EARTH_RADIUS 6371.0
#define MU (3.0e11)
#define PI 3.1415927
#define D2R 0.0174532
#define SUNIT (1.0e-9)
#define KAPA 0.25
#include <stdio.h>
struct point {
double x;
double y;
};
typedef struct point Point;
extern int enclose(Point *, int, Point);
extern int enclose2(Point *, int, Point, Point);
extern int lenclose(Point *p, int n, Point p1);
extern int lenclose2(Point *p, int n, Point p1, Point p2);
extern double azimuth(double, double);
extern double atan2d(double, double);
extern double sind(double);
extern double cosd(double);
extern double dsign(double);
extern double dmax(double, double);
extern double dmin(double, double);
extern double diag_len(Point p[]);
extern void make_tensor(double z[][3], double, double, double);
extern void read_a_line(FILE *);
extern void strip_a_line(FILE *);
extern char *get_a_string(FILE *f, char* str);
extern int line_to_string(FILE *f, char* str);
extern int in_region(int node[], int N, int p);
extern double convert_date_to_year(int);
eqf.h
#define MAXP 10
#define MAXN 400
#define MAXB 1000
#define MAXF 37000
#define MAXE 1000
#define TYPE_F 1
#define TYPE_E 0
#define T 149
#define DEPTH 15.0
#define NSEG 2074
#include <stdio.h>
#include "gen.h"
struct earthquake {
int date;
Point loc;
double mom[3][3];
double m0;
int type;
};
struct merr {
double m[3][3];
};
struct mom {
double m0;
double mxx;
double myy;
double mxy;
};
struct region {
Point p[33];
double area;
double t0;
struct earthquake event[50];
int ne;
struct earthquake *e[100];
double strainrate[9];
double strain[9];
double strainr[9];
double strain0[9];
};
struct regionf {
Point p[33];
double area;
int ix;
int iy;
int ia;
};
struct fault {
double strike;
double rake;
double dip;
double rate;
double ratemin;
double ratemax;
char name[50];
int date;
int n;
Point xy[NSEG];
};
extern void test();
extern void read_faults(FILE *inf, struct fault *f);
extern void test_mom();
extern void print_event (FILE *inf, struct earthquake e);
extern int bydate(struct earthquake *, struct earthquake *);
extern void sort_event(FILE *);
extern int write_mom_tensor(struct earthquake *, int *, double);
extern void fill_regionf(struct regionf *, int *);
extern void fill_region(struct region *, int *);
extern void print_mom_in_region(struct region *b, int nb);
extern double strain_rate(double ex, double ey, double exy);
extern double strain_rate_var(double ex, double ey, double exy, double dex, double dey, double dexy, double cxy, double cxxy, double cyxy);
strain_from_faults_new.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "gen.h"
#include "eqf.h"
void deal_with_options(int, char **);
int no_faults, n_events;
double sdepth;
double ub = 0.01;
char faultin[25];
FILE *strain1;
int main(int argc, char *argv[]) {
Point p[MAXN], p1[10];
struct fault f[MAXF];
struct regionf b[MAXB];
double plat=0.0, plon=0.0, prat=0.0;
int n=0, i, j, nb=0, np, num, ia, k, l, nrect=0, nfree=0, ix=0, iy=0;
FILE *faults, *strain0;
sdepth = DEPTH*1.0e5;
strcpy(faultin, "fault.in");
deal_with_options(argc, argv);
if( (faults = fopen(faultin, "r")) == NULL ) {
printf("Error: File %s does not exist.\n", faultin);
exit(-1);
}
if( (strain0 = fopen("spline_fit.dat", "r")) == NULL) {
printf("Error: File spline_fit.dat cannot open\n");
exit(-1);
}
if( (strain1 = fopen("strain_from_faults.dat", "w")) == NULL) {
printf("Error: File strain_from_faults.dat cannot open\n");
exit(-1);
}
fscanf(strain0, "%d%d%d", &ix, &iy, &num);
fscanf(strain0, "%d", &nfree);
fprintf(strain1, "%10d %10d %10d\n", ix, iy, num);
fprintf(strain1, "%10d\n", nfree);
for(i=nfree; i<num; i++) {
if(fscanf(strain0, "%d%lf%lf%lf", &np, &plat, &plon, &prat) != 4) {
printf("Error: format error in spline_fit.dat\n");
exit(1);
}
fprintf(strain1, "%10d %10.3f %10.3f %12.6e\n", np, plat, plon, prat);
}
fscanf(strain0, "%d", &nrect);
fprintf(strain1, "%10d\n", nrect);
close(strain0);
for(i = 0; i < nrect; i += MAXB) {
nb = i;
printf("Working on regions %d to %d ...\n", i, i+MAXB);
fill_regionf(b, &nb);
read_clip_faults(faults, f, b, nb);
}
return 0;
}
int read_clip_faults(FILE *inf, struct fault *f, struct regionf *b, int nb) {
int i, j, k, l, ib, jj, kk, ii, n, nf;
double x, y, dx, dy, d, mt[3][3], c, theta;
double sd, md, strainrate[9];
double clip_seg = 0.05;
struct mom m1;
struct mom m0;
struct merr m2;
struct fault f0;
Point p[100], p0;
i=0;
fseek(inf, 0, SEEK_SET);
while( (k = fscanf(inf, "%d%lf%lf%lf%lf%lf%s",
&n, &(f[i].rake), &(f[i].dip), &(f[i].ratemin),
&(f[i].rate), &(f[i].ratemax), f[i].name)) == 7) {
printf("Fault no. %d, %s\n", i, f[i].name);
f[i].rate = f[i].rate;
f[i].ratemin = f[i].ratemin;
f[i].ratemax = f[i].ratemax;
f[i].n = 0;
for(j=0; j<n; j++) {
if( (l = fscanf(inf, "%lf%lf", &(p[j].y), &(p[j].x))) != 2) {
printf("Error at fault %s, line %d in fault.in\n", f[i].name, j);
exit(1);
}
}
jj=0;
for(j=0; j<n-1; j++) {
k = 0;
while( k < nb && (l = enclose(b[k].p, 33, p[j])) == 0)
...
Following Mike Kinghan's comments, I added
#ifndef GEN_H
#define GEN_H
and
#endif
in the head and tail of the gen.h file, respectively. But it not doing well, here are the errors:
/tmp/ccteT25z.o: In function `read_clip_faults':
strain_from_faults_new.c:(.text+0x6a4): undefined reference to `enclose'
strain_from_faults_new.c:(.text+0x7c5): undefined reference to `enclose'
strain_from_faults_new.c:(.text+0xa14): undefined reference to `enclose'
strain_from_faults_new.c:(.text+0xa7b): undefined reference to `dsign'
strain_from_faults_new.c:(.text+0xaae): undefined reference to `dsign'
strain_from_faults_new.c:(.text+0xad9): undefined reference to `dsign'
strain_from_faults_new.c:(.text+0xb5a): undefined reference to `dsign'
...
you need to #include "gen.h" in eqf.h
If you read this:
In file included from eqf.h:12:0,
from strain_from_faults_new.c:6:
gen.h:11:8: error: redefinition of ‘struct point’
struct point {
^
In file included from strain_from_faults_new.c:5:0:
gen.h:11:8: note: originally defined here
struct point {
^
it tells you that struct point is defined twice in the same translation
unit, strain_from_faults_new.c, which is an error.
You have defined struct point in gen.h at line 11.
You have included gen.h at line 5 in strain_from_faults_new.c
You have also included gen.h at line 12 in eqf.h.
And finally you have included eqf.h at line 6 in strain_from_faults_new.c,
thereby including the definition of struct point again.
To avoid such problems, use header guards a.k.a include guards in every header you write,
e.g.
gen.h
#ifndef GEN_H
#define GEN_H
struct point {
double x;
double y;
};
typedef struct point Point;
#endif
This makes it harmless to include a header more than once in a translation unit.
And, don't pass header files in the compiler commandline:
gcc -o strain_from_faults_new strain_from_faults_new.c gen.h eqf.h
^^^^^ ^^^^^
A header file gets compiled by being #include-ed in a .c file, which
copies it into the translation unit.
You need to add #include "gen.h" in eqf.h and compile your program with the command:
gcc -o gen.h eqf.h strain_from_faults_new strain_from_faults_new.c;
Compiler will compile your program file according to your file input order.
i have 2 structs, i want to assign one struct to another, but when i print the results, it prints crap, the functions : "ver_tope" is on charge to do that , what am i doing bad?, here is the code:
#include <stdio.h>
#include <stdlib.h>
#define TAM 4
typedef struct{
char nomyap[40];
int edad;
}t_info;
typedef struct {
t_info pila [TAM];
int tope;
}t_pila;
void ver_tope(const t_pila *p, t_info *d);
int main()
{
t_pila pila;
t_info info;
//I CHARGE BOTH STRUCTS
ver_tope(&pila, &info);
return 0;
}
void ver_tope(const t_pila *p, t_info *d)
{
*d = p->pila[(p->tope)-1];
return ;
}
Try adding an initialisation for pila.tope in main() ex:
... //I CHARGE BOTH STRUCTS
pila.tope =2;
ver_tope(&pila, &info);
...
That stopped the segmentation fault...
int main()
{
t_pila pila;
t_info info;
ver_tope(&pila, &info);
return 0;
}
You have not initialized either variable. Since pila is the source of the assignment you can do the following:
int main()
{
t_pila pila = { 0 };
pila.tope = 1;
t_info info;
ver_tope(&pila, &info);
return 0;
}
Here I default initialized pila and then set its tope member to 1. I did not initialize info since ver_tope assigns to it. It would be clearer if you converted ver_tope into a function that returned t_info.