I have been fiddling with enums for a while and wanted to try to use them in a project. The project structure is as follows:
// protocol.h
#ifndef PROTOCOL_H
#define PROTOCOL_H
enum C_C {P_NORTH = 0,
P_WEST = 1,
P_SOUTH = 2,
P_EAST = 3};
#endif
// other.h
#include "protocol.h"
struct cmd {
enum C_C code : 4;
};
void make_cmd(struct cmd*, enum C_C);
This file triggers the following errors:
field 'code' has incomplete type
'enum C_C' declared inside parameter list will not be visible outside of this definition or declaration
// other.c
#include "other.h"
void make_cmd(struct cmd* cmd, enum C_C code) {
cmd->code = code;
}
This throws the following errors:
conflicting types for 'make_cmd'
I have tried changing the enum to a type using typedef with no luck. This happens also with function definitions which rely on this type of parameters.
Will throw the following error:
type of formal parameter 2 is incomplete
Thanks for your help.
This only happens when using the defined enum in another header, either for structs or for functions prototypes.
I do believe there must be some issue with the compilation order. I have tested in Xilinx SDK and Vitis with the same result.
protocol.h holds all the definitions of the enums and the structures to be used throughout the project. I was hoping by just including this one in the other headers the definitions would be available to build the other.h and other.c on top of that one.
Update:
I have moved the definition of the structure inside the protocol.h and it lets me add a member using the enum without issues. I guess the problem is when importing protocol.h into another header and trying to use the enum there the compiler has all of the headers in the
This code compiles:
#include "other.h"
void make_cmd(struct cmd* cmd, enum C_C code) {
cmd->code = code;
}
int main(int argc, char *argv[])
{
struct cmd cmd;
make_cmd(&cmd, P_WEST);
}
If you #include "protocol.h" as well you'll get an error (type redefinition) because it is already included in other.h.
Related
I've been developing in C using eclipse as my IDE in my virtual machine with ubuntu, I've made some progress and I wanted to test them in the real product which is an embedded system using powerpc.
In order to compile that program for our product I use Code::Blocks in Windows but the compiler is a powerpc version of the gcc.
The same code is giving me an error in the powerpc version that doesn't appear in the ubuntu version.
I have two header files gral.h and module_hand.h as follows:
The gral.h file:
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
#include "module_hand.h"
typedef struct PROFILE
{
module_t mod; // this one comes from module_hand.h
int var1; // some other random variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */
The module_hand.h is defined as follows
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <stdint.h>
#include "gral.h"
typedef struct PROFILE profile_t;
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
int Mod_Init(profile_t *profile);
/* some other random functions */
#endif /* HEADERS_MODULE_HAND_H_*/
As you'll see, I don't use the PROFILE struct in the module struct, But I declare it forward to use it in the declaration of the Mod_Init function
This gives me a Error: redefinition of typedef 'profile_t'
and error: previous declaration of 'profile_t' was here
If I remove the forward declaration the error is Error: parse error before '*' token
where the line number is the line of the function declaration.
My doubt is what am I missing, and why gcc in Ubuntu does compile it with no problem.
Your powerpc compiler is enforcing the C99 rule that
If an identifier has no linkage, there shall be no more than one
declaration of the identifier (in a declarator or type specifier) with
the same scope and in the same name space, except for tags as
specified in 6.7.2.3.
(C99 6.7/3)
Your Linux compiler is observing the relaxed version of that rule that was introduced in C11:
If an identifier has no linkage, there shall be no more than one
declaration of the identifier (in a declarator or type specifier) with
the same scope and in the same name space, except that:
a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;
tags may be redeclared as specified in 6.7.2.3.
(C11 6.7/3; also C17 6.7/3)
Supposing that the compilation options are the same, the behavior difference surely arises from using different versions of GCC. More recent versions default to more recent versions of the language.
You could try adding -std=gnu11 or -std=c11 to the command-line options (for both targets) to try to get consistency. If your powerpc version of GCC is too old to accept those then you really need to update to a newer version.
Note also, however, that you don't need to have this problem in the first place. Given that module_hand.h includes gral.h, the former has no need whatever to redefine a typedef that the latter already defines.
Moreover, the fact that these two headers each include the other is a strong suggestion that they ought to be combined into one. Multiple-inclusion guards prevent an actual loop, but they are not an adequate solution.
In the gral.h header file, you define profile_t using typedef, then you redefine profile_t with another typedef in module_hand.h. You should just define the struct PROFILE in gral_h and include gral.h in module_hand.h.
gral.h:
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
#include "module_hand.h"
typedef struct PROFILE {
module_t mod; // this one comes from module_hand.h
int var1; // some other random variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */:
module_hand.h:
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <stdint.h>
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
int Mod_Init(struct PROFILE *profile);
/* some other random functions */
#endif /* HEADERS_MODULE_HAND_H_*/
Well I read your answers and comments and decided to try another approach.
As some of you said, I had some kind of recursion, I wanted to keep every structure within its respective header file, but now, I dropped the idea and merged the structures in one file only.
My new approach:
Gral.h
#ifndef HEADERS_GRAL_H_
#define HEADERS_GRAL_H_
typedef struct module
{
char name[30]; // name of module
char rev[30]; // module revision
char mfr[30]; // manufacturer
} module_t;
typedef struct PROFILE {
module_t mod; // this one comes from module_hand.h
int var1; // some other variables
} profile_t;
#endif /* HEADERS_GRAL_H_ */:
Module.h
#ifndef HEADERS_MODULE_HAND_H_
#define HEADERS_MODULE_HAND_H_
#include <Gral.h>
int Mod_Init(profile_t *profile);
/* some other functions */
#endif /* HEADERS_MODULE_HAND_H_*/
And when any other structure comes up, I'll declare it in Gral.h and include the header file.
Regarding the compilers, they aren't the same version. The powerpc is quite old now. That would explain the powerpc compilation errors.
Thank you again.
I have a program spread through 3 different C files, with the 2 header files that come with it. I originally had the header "Player.h" that I used to save the "map" structure (among others):
#ifndef PLAYER_H_INCLUDED
#define PLAYER_H_INCLUDED
typedef struct map{
float x;
float y;
}map;
/// some other functions and structures///
#endif
I wanted to move it to its own header file, "Map.h" so its with the other map-related functions and structures.
#ifndef MAP_H_INCLUDED
#define MAP_H_INCLUDED
typedef struct map{
float x;
float y;
}map;
#endif
I made the Map.c file as normal, wrote a function in it that would work, but I didn"t call for the function in main.c yet.
I made the "map" data structure in main.c as followed:
#include "Player.h"
#include "Map.h"
int main(){
... /// some other stuff being done
map map;
map.x = 0;
map.y = 0;
... /// more stuff being done
callfunctioninplayer(&map, /// other variables///)
}
so I call the function in player.c, where I also included map.h using #included "Map.h". But after trying to compile it, it gave me an error everywhere where I asked for the map* map structure with the errors:
In file included from ./main.c:10:0:
./Player.h:21:55: error: unknown type name ‘map’
void movementPlayer(int* inputPlayer, player* player, map* map, unsigned int countFrames);
./Player.h:21:55: error: unknown type name ‘map’
void movementPlayer(int* inputPlayer, player* player, map* map, unsigned int countFrames);
^~~
In file included from ./Map.c:10:0:
./Player.h:21:55: error: unknown type name ‘map’
void movementPlayer(int* inputPlayer, player* player, map* map, unsigned int countFrames);
I checked if map.h was defined everywhere, it is, and I tested it again after putting the map struct back in player.h. Putting it back in player.h worked, but why didn't it in map.h?
I'm sorry if this is asked a lot, I looked through some posts but couldn't find anyone with the same error
It looks like map is being used in Player.h, but Map.h hasn't been included at the point Player.h is included, and presumably you didn't include Map.h in Player.h.
If Player.h needs definitions in Map.h, then you need to #include "Map.h" in Player.h.
I'm trying to compile this code in c. First of all i have this struct in a separate source file to use it like a "class" (dir.h)
//Structure
typedef struct s_dirobject {
int noteid;
char title[20];
int bytes;
char head[20];
bool is_dir;
struct s_dirobject* next;
} dirobject;
//Ops
void add_dirobject(dirobject* myDirobject,int num_dirobject, char title[20], int is_dir, int bytes, char head[20]);
int get_dirobject_noteid(dirobject* myDirobject,int num_note);
char* get_dirobject_title(dirobject* myDirobject,int num_note);
int get_dirobject_bytes(dirobject* myDirobject,int num_note);
char* get_dirobject_head(dirobject* myDirobject,int num_note);
bool isdir(dirobject* myDirobject, int num_note);
int get_dirobjects_len(dirobject* myDirobject);
void clear_dir(dirobject* myDirobject);
void init_dir(dirobject* myDirobject);
In second place i have the comms source to retrieve the contents of a directory from a remote file system, and fill the object (comms.c)
#include "notebook.h"
#include "dir.h"
dirobject* temporaldirobjects;
...
init_dir(temporaldirobjects);
while(cond) {
//Add retrieved item to the directory
add_dirobject(temporaldirobjects, index, title, is_dir, bytes, "");
}
//When done retrieving the contents from the source i do instantiate the notebook_window
notebook_init(source, path, temporaldirobjects);
Finally, my notebook window interface will look like this. (notebook.h)
#include "dir.h"
void notebook_init(char* source, char* path, dirobject* contents);
void notebook_deinit();
And its implementation (notebook.c)
void notebook_init(char* source, char* path, dirobject* contents) {
// Fill the vars
this_window_source=source;
this_window_path=path;
this_window_dirobjects=contents;
...
}
When i compile this code as is, i get the error saying that
../src/dir.h:13:16: error: redefinition of 'struct s_dirobject'
In file included from ../src/notebook.h:12:0,
from ../src/comms.c:25:
../src/dir.h:13:16: note: originally defined here
In file included from ../src/comms.c:27:0:
../src/dir.h:20:3: error: conflicting types for 'dirobject'
In file included from ../src/notebook.h:12:0,
from ../src/comms.c:25:
../src/dir.h:20:3: note: previous declaration of 'dirobject' was here
In file included from ../src/comms.c:27:0:
../src/dir.h:23:6: error: conflicting types for 'add_dirobject'
In file included from ../src/notebook.h:12:0,
from ../src/comms.c:25:
../src/dir.h:23:6: note: previous declaration of 'add_dirobject' was here
...
since the comms library includes dir.h and notebook.h, and notebook.h does it too.
and if i remove the include in notebook.h i got this other error:
In file included from ../src/comms.c:25:0:
../src/notebook.h:14:46: error: unknown type name 'dirobject'
How can i acheive this? I would like to keep it as clean code as i can.
You included two headers in file comms.c
#include "notebook.h"
#include "dir.h"
header notebook.h in turn includes header dir.h
#include "dir.h"
void notebook_init(char* source, char* path, dirobject* contents);
void notebook_deinit();
As result the structure is defined twice in the same compilation unit. You have to provide that each headers would be included only once in each compilation unit. To do this you have to supply header's quards. For example
#ifndef DIR_H
#define DIR_H
//Structure
typedef struct s_dirobject {
int noteid;
char title[20];
int bytes;
char head[20];
bool is_dir;
struct s_dirobject* next;
} dirobject;
//...
#endif
Or if the compiler supports #pragme once then you could use it.
Usually, multiple declarations are fine in c but multiple definition is not. In your code, you are including dir.h multiple times which is causing the redefinition of struct s_dirobject. Read something about "Header guard" or "Include Guard". here. Hope this solves your major issues with redefinitions.
I have errors when compiling my project with codeblocks.
My problem comes from a enum definition, and from a struct definition.
They are bot defined in a header file, that worked since i was only using those enum and struct in the .c associated file. But when i include the .h file in another .c file, i get errors, here is some code;
maps.h
#include <stdlib.h>
#include <stdio.h>
enum Property { BACKGROUND, FOREGROUND, BLOCK, EVENT };
typedef struct {
char map_name[50];
int width;
int height;
char* map_struct;
}rpgMap;
char getTileProperty(rpgMap map, int x, int y, int property);
maps.c
#include "maps.h"
char getTileProperty(rpgMap map, int x, int y, int property){ // Works
char value = NULL;
value = map.map_struct[(((y*(map.width-1))+y+x) * 4 ) + property];
return value;
}
rpgMap loadMap(unsigned char* map){
rpgMap Map;
//....
//some code
//...
return Map;
}
// This works until i include maps.h in another .c file
So here's the stuff, when i include maps.h in eg. game.c or game.h i have this error;
error: nested redefinition of 'enum Property'
I don't get it !
You need to add header guards to your header files otherwise you will get multiple declarations.
For example, for your maps.h surround it with this:
#ifndef MAPS_H
#define MAPS_H
...
#endif
Any source file that includes your header file will declare a single instance variable with the possible enumerated values of { BACKGROUND, FOREGROUND, BLOCK, EVENT }. I'm not sure that this is your intention. In general it is not good practice to do so.
If you intended to declare a type of enumeration and allow instances to be created elsewhere, put this in your header file:
typedef enum { BACKGROUND, FOREGROUND, BLOCK, EVENT } Property_t;
And then in your source files, declare the enumeration like so:
static Property_t property = BACKGROUND;
If you intended to create a variable that can be accessed from multiple source files then do put this in your header file:
typedef enum { BACKGROUND, FOREGROUND, BLOCK, EVENT } Property_t;
extern Property_t property;
and in a single source file, declare the variable:
Property_t property = BACKGROUND;
I'm just getting started with modular programming in C. I think I'm doing something wrong with the inclusions, because I'm getting a lot of conflicting types for 'functionName' and previous declaration of 'functionName' was here errors. I did put inclusion guards in place.
Do you know a clear tutorial that explains modular programming in C, especially how the inclusions work?
Update: I have tried to isolate my issue. Here's some code, as requested.
Update 2: updated code is below. The errors have been updated, too.
/*
* main.c
*/
#include <stdio.h>
#include "aStruct.h"
int main() {
aStruct asTest = createStruct();
return 0;
}
/*
* aStruct.h
*/
#ifndef ASTRUCT_H_
#define ASTRUCT_H_
struct aStruct {
int value1;
int value2;
struct smallerStruct ssTest;
};
typedef struct aStruct aStruct;
aStruct createStruct();
#endif /* ASTRUCT_H_ */
/*
* smallerStruct.h
*/
#ifndef SMALLERSTRUCT_H_
#define SMALLERSTRUCT_H_
struct smallerStruct {
int value3;
};
typedef struct smallerStruct smallerStruct;
smallerStruct createSmallerStruct();
#endif /* SMALLERSTRUCT_H_ */
/*
* aStruct.c
*/
#include <stdio.h>
#include "smallerStruct.h"
#include "aStruct.h"
aStruct createStruct() {
aStruct asOutput;
printf("This makes sure that this code depends on stdio.h, just to make sure I know where the inclusion directive should go (main.c or aStruct.c).\n");
asOutput.value1 = 5;
asOutput.value2 = 5;
asOutput.ssTest = createSmallerStruct();
return asOutput;
}
/*
* smallerStruct.c
*/
#include <stdio.h>
#include "smallerStruct.h"
smallerStruct createSmallerStruct() {
smallerStruct ssOutput;
ssOutput.value3 = 41;
return ssOutput;
}
This generates the following error messages:
At aStruct.h:10
field 'ssTest' has incomplete type
At main.c:8
unused variable `asTest' (this one makes sense)
The base of inclusion is to make sure that your headers are included only once. This is usually performed with a sequence like this one:
/* header.h */
#ifndef header_h_
#define header_h_
/* Your code here ... */
#endif /* header_h_ */
The second point is to take care of possible name conflicts by handling manually pseudo namespaces with prefixes.
Then put in your headers only function declarations of public API. This may imply to add typedefs and enums. Avoid as much as possible to include constant and variable declarations: prefer accessor functions.
Another rule is to never include .c files, only .h. This is the very point of modularity: a given module dependant of another module needs only to know its interface, not its implementation.
A for your specific problem, aStruct.h uses struct smallerStruct but knows nothing about it, in particular its size for being able to allocate an aStruct variable. aStruct.h needs to include smallerStruct.h. Including smallerStruct.h before aStruct.h in main.c doesn't solve the issue when compiling aStruct.c.
The multiple definition problem is most likely coming from the way you're including the code. You are using #include "aStruct.c" as opposed to #include "aStruct.h". I suspect you are also compiling the .c files into your project in addition to the #include. This causes the compiler to become confused due to the multiple definitions of the same function.
If you change the #include to #include "aStruct.h" and make sure the three source files are compiled and linked together, the error should go away.
Such errors mean that function declaration (return type or parameter count/types) differs from other function declarations or function definition.
previous declaration message points you to the conflicting declaration.