First of all, I've googled the error and read these answers:
I don't understand why compiler is giving me error with this code
C : Warning about visibility of a struct
But none of them helped me, so here we are.
The problem resides somewhere in between these 2 structures, prx_data_s which store generic data and prx_ops_s that defines pointers to functions that will use that data.
I'll simplify the sources for the example:
prx_data.h
#ifndef PRX_EXAMPLE_DATA_H
#define PRX_EXAMPLE_DATA_H
#include "prx_ops.h"
struct prx_data_s {
enum prx_op_t op;
char *keyquery;
};
char *get_query(struct prx_data_s *dt);
#endif
prx_data.c
#include "prx_data.h"
char *get_query(struct prx_data_s *dt)
{
return dt->keyquery;
}
prx_ops.h
#ifndef PRX_EXAMPLE_OPS_H
#define PRX_EXAMPLE_OPS_H
#include "prx_data.h"
enum prx_op_t {
PRX_EXAMPLE_OP = 2
};
struct prx_ops_s {
int (*dec) (struct prx_data_s *);
};
#endif
I'm trying to compile the object from the above example with:
clang -c prx_data.c -o prx_data.o -std=c11 -g -Wall
And this is the output error:
In file included from prx_data.c:1:
In file included from ./prx_data.h:4:
./prx_ops.h:11:24: warning: declaration of 'struct prx_data_s' will not be visible outside of this function [-Wvisibility]
int (*dec) (struct prx_data_s *);
^
All help is welcome, thanks :)
You have a problem with circular dependencies in your header:
prx_data.h:
#include "prx_ops.h" <<< Here we do not yet see the struct definition
prx_ops.h:
#include "prx_data.h" <<<< Nothing will be included due to inclusion guards.
struct prx_ops_s {
int (*dec) (struct prx_data_s *); <<<< Here a new struct type is declared.
};
later back in prx_data.h:
struct prx_data_s {
enum prx_op_t op;
char *keyquery;
};
When reading prx_ops.h, you dont 't have prx_data.h included because the compiler is reading prx_ops.h from the include at the beginning of prx_data.h. You thus have to forward declare it.
Try adding
struct prx_data_s;
at the beginning of prx_ops.h`
Hope that helps ~~
Related
file tools.h:
//some macro definitions
struct name;
//other function prototypes
file tools.c:
#include "tools.h"
struct name
{
FILE *src;
int value;
}
//definitions of functions declared in tools.h
file main.c:
#include <stdio.h>
#include "tools.h"
int main()
{
struct name *ptr;
ptr = malloc(sizeof(struct name));
ptr->FILE = fopen(filename, "r");
ptr->value = 12;
...
}
At first, I built tools.o by using:
$ gcc tools.c -c
Without any error or warning, tools.o was built in the current directory.
Now, I tried to build executable by using:
$ gcc main.c tools.o -o exe
and I got errors of same type (all the errors were of same type, caused due to accessing the struct element). Here's the sample of that error I got:
main.c: In function ‘main’:
main.c:17:22: error: invalid use of undefined type ‘struct name’
17 | buffer = malloc(ptr->value+1);
Please explain why this happened and what wrong I did while linking or in my code.
tools.h file
#ifndef TOOLS_H
#define TOOLS_H
#include <stdio.h>
struct name
{
FILE *src;
int value;
};
int foo(struct name*);
struct name *bar(double, FILE*, const char *); //prototypes of functions defined in tools.c
#endif
tools.c
#include "tools.h"
int foo(struct name*)
{
/* ... */
}
struct name *bar(double, FILE*, const char *)
{
/* ... */
}
Looks like you have some confusion with regards to forward declaration of a structure and a structure declaration (which defines a type).
From Forward declaration:
a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.
In tools.h, this
struct name;
is forward declaration of structure struct name. Note that, it declares an incomplete type because the specification [list defining the content] of struct name is unknown at this time.
You have included the tools.h in main.c and when compiling main.c compiler does not find the specification of struct name and hence, throwing error on the statements using it.
In tools.c, you are declaring the struct name (which defines a type):
struct name
{
FILE *src;
int value;
};
when compiling tools.c, compiler knows about the specification of structure struct name and hence, it's compilation is successful.
The other post [by #0___________] gives the appropriate way to solve this problem.
I am building a project that I am trying to organize as follows:
main.c
globals.h
structures.h
FunctionSet1.c, FunctionSet1.h
FunctionSet2.c, FunctionSet2.h
etc.
I thought I could define a structure type in structures.h:
struct type_struct1 {int a,b;}; // define type 'struct type_struct1'
then declare a function1() returning a structure of type type_struct1 in FunctionSet1.h:
#include "structures.h"
struct type_struct1 function1(); // declare function1() that returns a type 'struct type_struct1'
then write function1() in FunctionSet1.c:
#include "FunctionSet1.h"
struct type_struct1 function1() {
struct type_struct1 struct1; // declare struct1 as type 'struct type_struct1'
struct1.a=1;
struct1.b=2;
return struct1;
}
Edit: with the corrected code above, the compiler returns
306 'struct' tag redefined 'type_struct1' structures.h
Is the file set good practice ?
What is the good practice to manage the structures ?
In your example, you declare a structure named type_struct in structure.h, then in FunctionSet1.h the structure that you are returning is type_struct, and in the .c it is called struct1.
So i think that the problem is that struct1 and type_struct are not recognized because they have never been defined ...
However, the organization of your files is fine.
Your general structure looks good. One thing you need to do, as zenith mentioned, is to put include guards into your header files. What that is is a set of #define's that make sure that the contents of the header are not included more that once in a given file. For example:
structures.h:
#ifndef STRUCTURES_H
#define STRUCTURES_H
struct type_struct1{
int a,b;
};
...
// more structs
...
#endif
FunctionSet1.h:
#ifndef FUNCTION_SET_1_H
#define FUNCTION_SET_1_H
#include "structures.h"
struct type_struct1 function1();
...
// more functions in FucntionSet1.c
...
#endif
main.c:
#inlcude <stdio.h>
#include "structures.h"
#include "FunctionSet1.h"
int main(void)
{
struct type_struct1 struct1;
struct1 = function1();
return 0;
}
Here, main.c includes structures.h and FunctionSet1.h, but FunctionSet1.h also includes structures.h. Without the include guards, the contents of structures.h would appear twice in the resulting file after the preprocesser is done. This is probably why you're getting the "tag redefined" error.
The include guards prevent these type of errors from happening. Then you don't have to worry about whether or not a particular header file was included or not. This is particularly important if you're writing a library, where other users may not know the relationship between your header files.
First of all, you have to declare the structure in your file.h (you can use typedef to create an alias)
typedef struct Books
{
char title[50];
int book_id;
} books;
then, you have to include your file.h in your file.c and declare your variable like this
#include "file.h"
int main()
{
books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
or like this if you didn't use typedef
#include "file.h"
int main()
{
struct Books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
Thank you all.
I read again what you said and found that the code above is now correct.
The error I report is with testing the following main.c
#include "structures.h"
#include "FunctionSet1.h"
void main() {
struct type_struct1 struct2;
struct2=function1();
}
in which structures.h is included again, thus causing the error. Removing the include eliminates the error.
I will now look into header guards to avoid such problems.
Thanks again.
I want to return a struct and print one of its members in main.
I am getting this error when trying to compile:
Main.c: In function ‘main’:
Main.c:8:2: error: invalid use of undefined type ‘struct busRoute’
Any help would be appreciated. I don't see why what I'm trying to do won't compile.
BusRoute.c
#include <stdio.h>
#include "BusRoute.h"
struct busRoute {
int busRouteNumber;
char *startingLocation;
char *endingLocation;
char driverName[36];
} route[STRUCT_SIZE] = {0};
//retrieves route info
struct busRoute getBusRouteInfo(unsigned int index)
{
return route[index];
}
void setStruct()
{
route[2].busRouteNumber = 5;
}
Main.c File
#include <stdio.h>
#include "BusRoute.h"
int main()
{
setStruct();
printf("%d",getBusRouteInfo(2).busRouteNumber);
}
Your struct busRoute should be defined in BusRoute.h, not BusRoute.c, if you want to use it in main.c. And you do want to use it in main.c, if your getBusRouteInfo() function returns one. Without main.c being able to see this definition, it doesn't know that struct busRoute even has a member named busRouteNumber, let alone how to get at it, so that's why compilation fails.
Your other option is to define a function like getBusRouteInfoRouteNumber(2), which will return the appropriate member indirectly. That way, main.c doesn't need to know anything about the actual struct busRoute.
When I compile the program, outlined below, I am getting the following error(s) back
[igor#localhost ~/I2C]$ make i2c_VIPER DEFINE=-DVIPER
gcc -g -Wall -D__USE_FIXED_PROTOTYPES__ -DVIPER -ansi -lusb -c -o i2c.o i2c.c
In file included from i2c.c:9:
viperboard.h:120: error: expected ‘)’ before ‘*’ token
i2c.c: In function ‘main’:
i2c.c:32: error: ‘usb_dev’ undeclared (first use in this function)
i2c.c:32: error: (Each undeclared identifier is reported only once
i2c.c:32: error: for each function it appears in.)
i2c.c:33: warning: implicit declaration of function ‘i2c_VIPER’
make: *** [i2c.o] Error 1
I've tried many things, more or less semi-blindly, to make it working. The struct parsed_CLI_I2C_t defined by me, works flawlessly. No compilation errors. But, when I try to use struct usb_device from <usb.h> in equivalent way, the compiler is not happy.
What I am doing wrong ?
Relatively detailed description follows.
Let's start with a code snippet from the standard #include < usb.h > <-- link to the full header file
/* Data types */
struct usb_device;
struct usb_bus;
struct usb_device {
struct usb_device *next, *prev;
char filename[PATH_MAX + 1];
struct usb_bus *bus;
struct usb_device_descriptor descriptor;
struct usb_config_descriptor *config;
void *dev; /* Darwin support */
u_int8_t devnum;
unsigned char num_children;
struct usb_device **children;
};
Here is the first local header file #include "viperboard.h"
struct parsed_CLI_I2C_t;
extern int i2c_VIPER (struct usb_device **usb_dev, struct parsed_CLI_I2C_t **CLI_I2C_options);
extern bool OpenDevice(void);
This is the second local header file #include "I2C.h"
typedef struct
{
char *USB_board;
int query;
int write_type;
} parsed_CLI_I2C_t;
extern int parse_CLI_I2C_options (int argc, char *argv[], parsed_CLI_I2C_t **CLI_I2C_options);
The main program looks like this
/* all other standard include stuff skipped for brevity */
#include <usb.h>
#include "viperboard.h"
#include <stdbool.h>
#include "I2C.h"
int main(int argc, char *argv[])
{
parsed_CLI_I2C_t *CLI_I2C_options;
parse_CLI_I2C_options (argc, argv, &CLI_I2C_options);
struct usb_device *usb_dev;
i2c_VIPER (&usb_dev, &CLI_I2C_options);
}
and, finally, this is the external module
i2c_VIPER.c
/* all other standard include stuff skipped for brevity */
#include <usb.h>
#include "viperboard.h"
#include <stdbool.h>
#include "I2C.h"
int i2c_VIPER (struct usb_device **usb_dev, struct parsed_CLI_I2C_t **CLI_I2C_options )
{
bool connected; /* True if the ViperBoard is connected */
connected = OpenDevice();
return(0);
}
This is
OpenDevice.c
#include <stdbool.h>
#include <usb.h>
bool OpenDevice() /* <---- this is line 11 */
{
usb_set_debug( 0 );
/* Initialize USB library */
usb_init( );
etc etc etc
return true;
}
========================================================
30 minutes later: all suggested changes implemented
Another type of error appeared.
OpenDevice.c:11: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘OpenDevice’
make: *** [OpenDevice.o] Error 1
This line
usb_device *usb_dev; /* this is line 32 */
will not work as you're compiling a C program, not a C++ program. In C structures are not automatically types like they are in C++. You need to use the struct keyword to declare structures:
struct usb_device *usb_dev; /* this is line 32 */
This change you have to do for every place where you use structures, for example like the declaration and definition of the i2c_VIPER function.
Also note that for the bool type to work, you need to include <stdbool.h>.
I'm implementing a sql parser in lex and yacc,
in that I use a symbol table which I kept in a separate .h file (sql.h) and in this header file I have some functions declarations.
The definitions of these functions are kept in a .c file (sql.c). Now I have included sql.h in sql.c,
I refer to the symbols and functions from sql.h in both my lex file(1.l) and yacc file(1.y).
The problem is that I'm not able to write a proper makefile for this.
I'm getting errors like multiple declarations.
Where do I include which file and how to write dependencies?
Please help. I have searched for a solution but I'm not getting it.....
Update:
I compile the code like this:
lex 1.l
yacc -d 1.y
gcc lex.yy.c y.tab.c sql.c -ll -ly
I get the following errors after the third command of gcc:
In file included from 1.l:5:
sql.h:17: warning: ‘SQL’ initialized and declared ‘extern’
sql.h:18: warning: ‘SQL_SEL’ initialized and declared ‘extern’
1.l: In function ‘makeTable’:
1.l:80: warning: assignment from incompatible pointer type
In file included from 1.y:7:
sql.h:17: warning: ‘SQL’ initialized and declared ‘extern’
sql.h:18: warning: ‘SQL_SEL’ initialized and declared ‘extern’
sql.c:3: error: redefinition of ‘SQL’
sql.h:15: note: previous definition of ‘SQL’ was here
sql.c:4: error: redefinition of ‘SQL_SEL’
sql.h:16: note: previous definition of ‘SQL_SEL’ was here
sql.h:
#ifndef SQL_H
#define SQL_H
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct sym_table {
char *token;
char *value;
struct sym_table *next;
};
struct sym_select {
char **cols;
};
extern struct sym_table *SQL = NULL;
extern struct sym_select *SQL_SEL = NULL;
void addSymbol(char *, char *);
void print(struct sym_table *);
void showTable(struct sym_table *);
void makeTable(struct sym_table *, int);
sql.c:
#include "sql.h"
struct sym_table *SQL = NULL;
struct sym_select *SQL_SEL = NULL;
And the definitions of the functions declared in sql.h
1.l file:
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
#include "sql.h"
int lineno=1;
void makeTable(struct sym_table *, int);
%}
..... and othr lex file
1.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int lineno;
extern void yyerror(char *);
#include "sql.h"
%}
.... and other yacc file data
Can you suggest me some other way to get around this?
Please post your Makefile. As far as i understand there's also a problem with code, not only with Makefile. Or it could be that you try to make 1.o from 1.l and different 1.o from 1.y.
Normally the dependencies should look something like:
1l.o: 1.l sql.h; # lex invocation
1y.o: 1.y sql.h; # bison invocation
sql.o: sql.c sql.h; # cc invocation
prog: 1l.o 1y.o sql.o; # ld invocation
Probably you will also need to depend on tokens' declaration file.
EDIT:
Ah, so probably you need to put the definition of that table into one file, and the declaration into the header. You must first understand the difference between declaration and definition in C. For example if you have the following files:
aaa.h
int arr[]={1};
aaa.c
#include "aaa.h"
bbb.c
#include "aaa.h"
And then you try to cc -o aaa aaa.c bbb.c, you get the multiple definition error. That means, that the actual array must be in one file, and in the header it should be something like extern int arr[];
Update:
You should remove setting to NULL in sql.h. It's only a declaration there, that there is such and such variable somewhere. The actual value is to be assigned in sql.c.
extern struct sym_table *SQL = NULL;
extern struct sym_select *SQL_SEL = NULL;
Remove the initialization = NULL from the header file.