Right way to call headers in c - c

I'm new in c programming.
I'm playing with an exercise where I created a main program called main.c that includes two other modules: modulo1 and modulo2 with rispettives headers.
Modulo1 contains some data and functions while modulo2 calls data and functions defined modulo1.
I put the lists:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "modulo1.h"
#include "modulo2.h"
vector v1;
vector v2;
vector sm;
int
main (int argc,
char *argv[])
{
create(& v1 ,1 ,2 );
create(& v2 ,3 ,2 );
sum(& sm, & v1, & v2);
report (& v1);
report (& v2);
report (& sm);
printf("\n-----------------\nDone !\n-----------------\n");
return EXIT_SUCCESS;
}
Where
modulo1.h
struct vector
{
int x;
int y;
};
typedef struct vector vector;
void create(vector *v, int x, int y);
void sum(vector *sum, vector *v1, vector *v2);
modulo1.c
#include "modulo1.h"
void create(vector *v, int x, int y)
{
v->x = x;
v->y = y;
}
void sum(vector *sum, vector *v1, vector *v2)
{
sum->x = v1->x + v2->x;
sum->y = v1->y + v2->y;
}
and then the second modulo2.h
//#include "modulo2.h"
void report(vector *v);
and the modulo2.c is
#include "modulo2.h"
#include <stdio.h>
void report(vector *v)
{
printf("\n------------------\n The vector is:\n x:=%d\n y:=%d\n------------------\n", v->x, v->y);
}
When I build all like this I get some errors similar to this:
....modulo2.h:2:13: error: unknown type name ‘vector’
while when I include in modula2.h the #include "modulo1.h" I get another groups of errors like this following:
.....modulo1.h:1:8: error: redefinition of ‘struct vector’
The makefile is very easy:
modula1_SOURCES = \
main.c \
modulo1.c \
modulo1.h \
modulo2.c \
modulo2.h
I cannot understand where is the error and where I'm wrong.
Someone can help me ?
I think there is something wrong at header / include files ?
Thank you
Marco

When I build all like this I get some errors similar to this:
....modulo2.h:2:13: error: unknown type name ‘vector’
Because modulo2.h uses identifiers declared in modulo1.h, it needs to include modulo1.h.
… when I include in modula2.h the #include "modulo1.h" I get another groups of errors like this following:
.....modulo1.h:1:8: error: redefinition of ‘struct vector’
Because main.c includes modulo1.h and includes modulo2.h and the latter also includes modulo1.h, we have modulo1.h included twice, and so there are multiple definitions.
A way to resolve this is to use what are called header guards. In modulo1.h, we can put these lines at the beginning and the end:
#if !defined modulo1_h
#define modulo1_h
…
#endif // #if !defined modulo1_h
This will cause the contents of modulo1.h between those lines to be compiled only once:
The first time modulo1.h is included, modulo1_h is not defined, so !defined modulo1_h is true, and everything in the file is compiled.
That includes defining modulo1_h (with an empty replacement list).
The second time modulo1.h is included, modulo1_h is already defined, so !defined modulo1_h is false, and the rest of the file is not compiled.
This way, each file, whether it is main.c, modulo2.h, or another file can include modulo1.h if it needs any identifiers from that header, and it does not have to be concerned with whether anything has included it previously. If it has been included previously, there will be no multiple definitions. If it has not been included previously, its definitions (and declarations) will be applied.

Related

Avoid circular dependency in header files in C

I have two header files that refer to each other and that produce a compile error if I do not carefully put my includes on the right lines. Each of my header files matches with a srcs directory:
___include
|____matrixes.h
|____define.h
|____transformations.h
|____tuples.h
|____pixels.h
|____ppm.h
|____Myproject.h
|____error_handler.h
|____graphics.h
Basically, Myproject.h contains all #include I needed, while every other header files contain prototypes, typedefs, structs, #defines I needed for the respective srcs directory. But I guess I got something wrong.
My problem comes from pixels.h, graphics.h and (maybe) Myproject.h. Here are they:
#ifndef PIXELS_H
# define PIXELS_H
# include "Myproject.h"
typedef uint32_t t_pixel;
typedef unsigned char t_color;
//////////////////////////
//# include "graphics.h"
//////////////////////////
// pixels/conversions.c
t_tuple pixel_to_point(t_image image, int i, int j);
t_tuple point_to_pixel(t_image image, double x, double y);
// pixels/print.c
void print_pixel(t_pixel p, char *name);
// pixels/pixels.c
t_pixel pixel(t_color r, t_color g, t_color b, t_color a);
t_color get_a(t_pixel pixel);
t_color get_r(t_pixel pixel);
t_color get_g(t_pixel pixel);
t_color get_b(t_pixel pixel);
// pixels/ops.c
t_pixel add_pixel(t_pixel p, t_pixel q);
t_pixel sub_pixel(t_pixel p, t_pixel q);
t_pixel scal_pixel(float q, t_pixel p);
t_pixel mul_pixel(t_pixel p, t_pixel q);
#endif
#ifndef GRAPHICS_H
# define GRAPHICS_H
# include "Myproject.h"
typedef struct s_window{
void *mlx;
void *win;
} t_window;
typedef struct s_image {
void *mlx;
void *img;
char *addr;
int bits_per_pixel;
int line_length;
int endian;
t_tuple origin;
t_tuple extension;
} t_image;
typedef struct s_canvas{
t_window window;
t_image image;
} t_canvas;
// graphics/graphics.c
t_window *window(t_window *cvs);
t_image *image(t_image *img, void *mlx);
t_canvas *canvas(t_canvas *canvas);
void put_pixel(t_image img, int x, int y, t_pixel pixel);
// graphics/free.c
void free_window(t_window *window);
void free_image(t_image *image);
void free_canvas(t_canvas *canvas);
#endif
#ifndef MYPROJECT_H
# define MYPROJECT_H
# include <unistd.h>
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <limits.h>
# include <stdbool.h>
# include <mlx.h>
# include <math.h>
# include <fcntl.h>
# include <sys/stat.h>
# include "libft.h"
# include "define.h"
# include "tuples.h"
# include "matrixes.h"
# include "pixels.h"
# include "graphics.h"
# include "ppm.h"
# include "error_handler.h"
# include "transformations.h"
#endif
As such, it did not compile with following error:
In file included from srcs/pixels/conversions.c:13:
In file included from include/miniRT.h:30:
include/pixels.h:22:24: error: unknown type name 't_image'
t_tuple pixel_to_point(t_image image, int i, int j);
^
include/pixels.h:23:24: error: unknown type name 't_image'
t_tuple point_to_pixel(t_image image, double x, double y);
I understand the error because the pixel_to_point function takes a t_image as argument and in Myproject.h, graphics.h is included after pixels.h so it does not recognize the t_image type.
If I try to invert the graphics.h and pixels.h includes in Myproject.h, I just get the same error when a function from graphics.h needs the t_pixel type.
I can make it run by uncommenting the commented #include graphics.h in pixels.h (because it is AFTER the t_pixel typedef) but I feel it is an ugly method.
Is there a rule to follow to avoid these issues ?
Consider your project include files to form some sort of hierarchy.
Have pixel.h only include "tuples.h", etc. What is needed, not "Myproject.h".
Likewise for "graphics.h".
Other strategies exist.
IMO, typedef unsigned char t_color; should not exist in "pixels.h", but only in "color.h".
IOWs, I recommend that each object/function/constant/macro declared in a xyz.h begin with a xyz_ or the like. OP's current approach has names spaces all over the place defined in a given .h file. I see this as hard to follow and unnecessarily difficult to maintain.
I would also recommend to rename functions like add_pixel() to pixel_add() to lead with the key-prefix pixel.

C Preprocessor include directive

When I include another source(I.e stdio.h) the preprocessor is smart enough to include only the functions that I am using in my code?
Example: Assuming this small program, would be ease to include only what I am using, and what the printf functions uses, including them recursively, but what about bigger programs?
#include <stdio.h>
int main(void) {
printf("Hello World\n");
return 0;
}
No. On the contrary:
#include performs textual replacement: it opens the file and copies all1 of its contents into your main C file. In the process it executes all preprocessor instructions in the included file. Amongst other things, this means that it will recursively include all files that are #included in the header.
#include does not know and does not care which part of the included file you end up using.
1 As mentioned, preprocessor instructions are executed in the included file. This can modify what gets included. For example, assume the following header file header.h:
#ifndef HEADER_H
#define HEADER_H
#ifdef NDEBUG
# define LOG(...) ((void) 0)
#else
# define LOG(...) log_message(__FILE__, __LINE__, __VA_ARGS__)
inline void log_message(const char* filename, int line, ...) {
// Logging code omitted for brevity.
}
#endif
// other stuff
#endif
Now, if your main.c file looks as follows:
#define NDEBUG
#include "header.h"
int main(void) {
// …
LOG("hello");
}
… then, after preprocessing, your main.c file would looks something like this (I’m omitting some irrelevant stuff):
# 1 "main.c"
# 1 "./header.h" 1
# 13 "./header.h"
// other stuff
# 3 "main.c" 2
int main(void) {
// …
((void) 0);
}
… in other words, only the part of header.h that corresponds to #ifdef NDEBUG was included, not the part in the #else clause. If we had included header.h without defining NDEBUG, then the included header code would have contained the definition of log_message.
As others have said, #include will paste verbatim the entire file you are targeting. However you normally include headers, which tend to look like
extern int a (int b);
extern char * c (void);
static inline int d (int e, int f) {
...
}
extern void * g (void * h);
...
The code above occupies exactly zero memory (unless you start using one of the inline functions), since it is entirely composed of instructions for the compiler and nothing else.

Trouble with using a special type in two header files. (C code)

I'm having trouble using a special type I made in two header files. One header files defines the type, the other one uses it in an extern variable, and a function.
"newtype.h"
typedef struct {
double i, s;
} newtype_t;
newtype_t this(){}
newtype_t that(){}
Now I have another header with a variable and function:
"newfuncs.h"
extern newtype_t c;
newtype_t divide(double d, double e);
I'm getting:
unknown type name 'newtype_t' //inside of "newfuncs.h"
This new header "newfuncs.h" is an addition to already working code that utilizes the new type and functions from "newtype.h".
I'm using this newtype_t inside of newfuncs.h.
I tried to #include "newtype.h" but I get a multitude of errors involving "conflicting types" in my .c files.
If a header use a type declared in another header, it should include it.
To prevent multiple declaration problem, you should add a guard in your header files:
// file newtype.h
#ifndef NEWTYPE_H // the guard
#define NEWTYPE_H
// all header stuff goes here
typedef int my_type;
#endif // end of guard
By doing this, each type or function will only be defined once. Each guard macro should be unique, you can use the file name to choose its name.
Some compiler (like cl) have a special comment to prevent multiple inclusion: #pragma once
did you included the header files in the right order?
I just tested it and it works
test.c
#include "newtype.h"
#include "newfuncs.h"
#include <stdio.h>
int main(){
double d = 4.0;
double e = 2.0;
c = divide(d, e);
printf("HELLO WORLD\n");
printf("%lf", c.i);
printf("%lf", c.s);
return 0;
}
newtype_t divide(double d, double e){
newtype_t x;
x.i = d;
x.s = e;
return x;
}
newtype.h
#ifndef NEWTYPE_H
#define NEWTYPE_H
typedef struct {
double i, s;
} newtype_t;
#endif
newfuncs.h
#ifndef NEWFUNCS_H
#define NEWFUNCS_H
newtype_t c;
newtype_t divide(double d, double e);
#endif
but even without the define it works for me (gcc 5.3.1).

error: expected ')' before '*' token

I have this include file (memory .h)
#ifndef MEMORY_H
#define MEMORY_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct mmemory {
int* cells;
int* current_cell;
int cells_number;
} memory;
void memory_init(memory* mymemory, int size);
void step_left(memory* mymemory, int steps);
void step_right(memory* mymemory, int steps);
void cell_inc(memory* mymemory, int quantity);
void print_cell(memory* mymemory);
void get_char(memory* mymemory);
#ifdef __cplusplus
}
#endif
#endif /* MEMORY_H */
And this implementation file (memory.c)
#include <stdlib.h>
#include "memory.h"
void
memory_init (memory* mymemory, int size)
{
mymemory->cells = (int*) malloc (sizeof (int) * size);
mymemory->cells_number = size;
mymemory->current_cell = (int*) ((mymemory->cells_number / 2) * sizeof (int));
}
... //other function definitions follow
When I try to compile memory.c I get this error for each and every function definition
src/memory.c:5: error: expected ')' before '*' token
where line 5 is the function definition for memory_init()
Can someone please tell me why I'm getting this error?
Because the system memory.h is shadowing your memory.h, causing the #include to succeed without declaring your types. Several possible fixes:
Rename your file -- probably for the best in any case, to reduce potential confusion.
Include your file via a prefix subdirectory (e.g., #include <myproj/memory.h>).
Move your file into the same directory as the source file, allowing the #include precedence rules for filenames wrapped in " to take effect.
Ensure that your C pre-processor include path options place your project header path prior to the system header paths.
This answer is really late, but I encountered a similar problem.
I think your problem is related to a typo in your .h file where you declare a struct mmemory. If you remove that extra 'm' it should work.
In your code you have defined like this for memory.h
#ifndef MEMORY_H
#define MEMORY_H
...
...
#endif
In case any of your other files which you use in your project is having the same #define i.e MEMORY_H then you can get this error.
Solution:
#ifndef XYZ_MEMORY_H
#define XYZ_MEMORY_H
...
...
#endif

how do i avoid this linking error?

if i have defined a global variable(with initialization) in header file, and included this file in two file and try to compile and link, compiler gives linking error
headers.h:
#ifndef __HEADERS
#define __HEADERS
int x = 10;
#endif
1.c:
#include "headers.h"
main ()
{
}
2.c:
#include "headers.h"
fun () {}
The linker complains because there will be multiple definitions of x once it puts all the object files together to create the executable. You have two different source files including the same header file, and that header file defines a variable x having a value of 10, so you end up with two definitions of x (one in 1.c and another in 2.c).
To avoid multiple definition linker errors, put this in a header file (for example globals.h):
#ifndef GLOBALS_H
#define GLOBALS_H
/*
* The "extern" keyword means that this variable is accessible everywhere
* as long as this declaration is present before it is used. It also means
* that the variable x may be defined in another translation unit.
*/
extern int x;
#endif
Then put this in one source file:
#include "globals.h"
int x = 10;
This is a classic case where you want either the variable declared or declared-and-defined.
If you define it in both source files, you will get a double-definition linker error. One way to handle this is to only set __HEADERS for one of the source files so that it is the one where the variable is defined.
All other source files get the declaration only.
>>headers.h
#ifndef __HEADERS
int x = 10;
#else
extern int x;
#endif
>>1.c
#define __HEADERS
#include "headers.h"
int main (void) {
return 0;
}
>>2.c
#include "headers"
void fun (void) {
}
Of course, it's best to leave definitions out of header files altogether in case you accidentally define __HEADERS in two source files. Try:
>>headers.h
extern int x;
>>1.c
#include "headers.h"
int x = 10;
int main (void) {
return 0;
}
>>2.c
#include "headers"
void fun (void) {
}
#include works exactly the same as if you copied and pasted the text from the header file.
Consider it in that way and you will see that you have therefore put the line int x=10 into both your source files.
A fixed version is below:
>>headers.h
#ifndef __HEADERS
#define__HEADERS
extern int x; // extern tells the compiler it will be linked from another file
#endif
-----------------
>>1.c
#include "headers.h"
int x = 10; // must have it in ONE file for linking purposes
main ()
{
}
---------------------
>>2.c
#include "headers"
fun () {}
Define __HEADERS in the ifndef.
Put declarations, not definitions, in your headers:
// header
extern int x;
// implementation
int x = 10;
3. 2.c has the include wrong.
So:
// headers.h
#ifndef __HEADERS
#define __HEADERS
extern int x;
#endif
// 1.c
#include "headers.h"
int x = 10;
main ()
{
}
// 2.c
#include "headers.h"
fun () {}
You can define x anywhere. Just make it one place.

Resources