C: Inclusions within Headers - c

If I have the following:
/*
* example.h
*/
#ifndef EXAMPLE
#define EXAMPLE
#include <stdio.h>
extern int parse_string(FILE *, char const*, const unsigned int);
#endif
Will this mean that code that uses ... #include example.h ... won't have to ... #include example.h's ... dependencies ? ( ie: #include <stdio.h> )

Yes
But if the code depends on <stdio>, it probably should include it. (After all, <stdio> has multiple inclusion protection as well.)
If what you want is a master include for your project, then go ahead and make one, but have it include both the actual headers and the common system headers, but no prototypes or declarations or macros. That is, have the mega include do nothing but includes. This way individual modules can make their own decisions down the line as the program evolves.

Correct - this is why its good practice to limit necessary headers included within other headers. The preprocessor will replace the "#include" directive with the contents of stdio.h,
so your header will look something like this to the compiler:
/*
* example.h
*/
#ifndef EXAMPLE
#define EXAMPLE
<contents of stdio.h>
extern int parse_string(FILE *, char const*, const unsigned int);
#endif

Yes, you can do that and it will have the desired effect.
For your particular example you need FILE declared in <stdio.h>, so it's good to include it.
If the parse_string() prototype used size_t instead of unsigned int and const char * (for a filename) instead of FILE *, I'd include <stddef.h> in the "example.h"
#ifndef EXAMPLE
#define EXAMPLE
#include <stddef.h> /* size_t typedef */
extern int parse_string(const char *filename, char const*, const size_t);
#endif

Related

Why can't I have an inner structure when two files include each other?

For context, I'm writing an operating system:
I have a struct vt_device_s and a struct __vt_device_s which is architecture specific and lives inside of vt_device_s like so:
struct
vt_device_s
{
struct __vt_device_s __device;
size_t cursor_x;
size_t cursor_y;
};
Now for the architectural struct:
struct
__vt_device_s
{
uint16_t *memory;
size_t memory_len;
};
The header <dev/vt.h> knows about __vt_device_s defined in <sys/_vt.h> because it is included, yet I get this error:
error: field '__device' has incomplete type
48 | struct __vt_device_s __device;
|
I realise this is because both files rely on each other (the whole conflict is caused by _vt.c including _vt.h including vt.h including _vt.h) but I don't understand how it is a compile problem. I have include guards in both files!
PS: I understand this would be a non-issue if I used a pointer but as it's an operating system, this driver needs to function before paging is set up (that is, malloc and free don't exist yet).
Here are the three files in question:
dev/vt.h
#ifndef _DEV_VT_H_
#define _DEV_VT_H_ 1
#include <stddef.h>
#include <sys/_vt.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct
vt_device_s
{
struct __vt_device_s __device;
size_t cursor_x;
size_t cursor_y;
};
void vt_init(struct vt_device_s *);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _DEV_VT_H_ */
sys/_vt.h
#ifndef _I386__VT_H_
#define _I386__VT_H_ 1
#include <stddef.h>
#include <stdint.h>
#include <dev/vt.h>
#define __VT_WIDTH 80
#define __VT_HEIGHT 25
#define __VT_MEMOFF 0xb8000
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct
__vt_device_s
{
uint16_t *memory;
size_t memory_len;
};
void __vt_init(struct vt_device_s *);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _I386__VT_H_ */
sys/_vt.c
#include <sys/_vt.h>
void
__vt_init(struct vt_device_s *device)
{
device->__device.memory = (uint16_t *) __VT_MEMOFF;
device->__device.memory_len = __VT_WIDTH * __VT_HEIGHT;
}
Your double include guards prevent the one file from including itself when it is re-included by the other. The only way to fix this is you have got to break the cycle. Decide which header is "higher" and will include the "lower" and don't try to include the higher one from the lower one. The lower one must be valid on its own.
The reason for this is that the pre-processor has to transform multiple files into one linear sequence of lines for the compiler. The compiler has to see one set of file contents before the other.
If you have cyclic includes like this you make it up to the final user of the code which one comes first. If they include file A, then it will include file B, which will try to include file A again but it will be prevented by the include guards, so the contents of B will be parsed first. On the other hand if the final user includes B first, then the contents of A will be seen first by the compiler.
So if you leave it like it is, then it is effectively random which file gets included first. If you break the cycle, you get to decide yourself which is included first.
Once you have decided, you can fix the compiler errors about incomplete types by making whichever file you choose to put first able to stand on its own and then letting the one that is second use definitions from the first.

#including files [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I got a problem with including files.
What I've basically made is a command-line program in C that works with a csv file. It has 5 commands: -menu, -add, -edit, -del, -verify. All is good except for the -menu. What needs to happen when I type "./passweb -menu" is for a visual menu to appear. This menu command should call a new function and it needs to be located in a separate c file (aka menu.c).
The problem I'm having right now is that I'm not too sure how to include the files to run in the menu.c because the way I have it set up right now, passweb.c has all the functions such as -add and -edit and etc. I know you need to make header files and such but it's complaining that I've declared the methods twice which is true since I use the functions in the menu file.
Here's some of the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cipher.h"
#include "menu.h"
#include "passweb.h"
#define MAXLENGTH 51 //longest length of a single record + 1 =51 bytes
#define SIZEOFDB 1000
#define ENCRYPT 5
typedef struct rec
{
char name[MAXLENGTH];
char pw[MAXLENGTH];
char type[6];
int boolean;
}RECORD;
int add(char *nName, char *nPw, char *nType, RECORD *arr, int size);
void del (char *tName, RECORD *arr, int size);
int edit(char *nName, char *nPw, char *nType, char *tName, char *tPw, RECORD *arr, int size);
int verify (char *tName, char *tPw, RECORD *arr,int size);
This is my main file "passweb.c" and it's declared the functions.
Later on in the main, I will call a menu function which is located in a menu.c file.
In the menu function I use "add","edit","del" and etc that I wrote in this .c file.
As you can see on the top, I have included the header files.
What can I do to solve this problem?
Sorry for the long post.
Thanks
You should put function prototype in the header file. You should put its implementation in the source file, which should include the header file.
For example, the header (test.h) would have the structure definitions and function prototypes like:
#ifndef TEST_H
#define TEST_H
struct myStruct {
int x;
};
int Add(int lhs, int rhs);
#endif
And the source would have:
#include "test.h"
#include <stdio.h>
int Add(int lhs, int rhs)
{
return lhs+rhs;
}
int main()
{
printf("%d",Add(2,3));
return 0;
}
put this in your header file and include it:
#ifndef FUNCS_H_
#define FUNCS_H_
int add(char *nName, char *nPw, char *nType, RECORD *arr, int size);
void del (char *tName, RECORD *arr, int size);
int edit(char *nName, char *nPw, char *nType, char *tName, char *tPw, RECORD *arr, int size);
int verify (char *tName, char *tPw, RECORD *arr,int size);
#endif /*FUNCS_H_*/
the #ifdef guards the header from multiple inclusion
Move the declaration of add, del, edit and verify in a new include file main.h
Include main.h in your main .c file and in menu.c
In general is also a good idea to put directives in the include files that tells the preprocessor to use them only once - Visual C++ has a special #pragma once directive for that, otherwise you can use
#if ! __MENU_C
#define __MENU_C
. . . .
#endif
The header file should contain your function prototypes and the necessary information about the data types they reference, such as your struct definitions. It may also include #define'ed constants, inline functions, declarations of extern variables (which would be declared normally inside one of your .c files), etc.
Once you have these things in your header file, you can remove them from the .c file(s); the actual function definitions, with the bodies, should be in the .c files -- but don't duplicate the prototypes there. You then #include the header in each .c file that needs the functions, etc. declared in it.
You also need to ensure that the items in the header file don't get #include'ed more than once in each source file, even indirectly (included from another include). Usually header guards are used for this, which use preprocessor conditionals to prevent processing of the header file when it has already been included:
#ifndef SOMEHEADER_H
# define SOMEHEADER_H
/* header file contents */
#endif
When compiling, you should be able to compile each .c file separately if you like, or all together if the compiler lets you. When linking, you need to link all the object files though. For gcc, doing both in one command, you might use something like this:
gcc -o program_name first.c second.c third.c
...which compiles each .c file to its own .o file, and links all of them together when producing the executable.

Most elegant way to share a C array

I have to turn back to (embedded) C after some lengthy time with C++, and have the following problem:
I have a source module which is included a lot of times, let's call it utilities.h and utilities.c
In it, I have an important array, let's call it
#define IMPORTANT_ARRAY_LENGTH 10000
char important_array[IMPORTANT_ARRAY_LENGTH];
I have a lot of other functions in this utilities module, and they all work fine. However, in one of the other source files, let's call it worker.c, I have to use this array. What is the "official", elegant way to do this, without having to put extern char important_array[IMPORTANT_ARRAY_LENGTH] and the macro definition in the worker.c ?
If I do the following:
utilities.h
#ifndef _UTILITIES_H_
#define _UTILITIES_H_
#define IMPORTANT_ARRAY_LENGTH 10000
extern char important_array[IMPORTANT_ARRAY_LENGTH];
// ...
utilities.c
#ifndef _UTILITIES_C_
#define _UTILITIES_C_
#include "utilities.h"
char important_array[IMPORTANT_ARRAY_LENGTH];
// ...
worker.c
#include "utilities.h"
// ...
important_array[0] = 0;
then my array will be an undefined symbol in worker.c. If I don't use the extern keyword in utilities.h, then of course, it's a duplicate symbol. (Strangely, it compiles with just a warning, and I can see from the linker file that the size is allocated multiple times.)
Do I really have to declare my array in worker.c? I want to keep everything clean, and have all declarations in one place only: in a header file. And I want to have the macro definition only once (this is secondary, because I could use a const, but I want the preprocessor to handle it, and not take up place)
What you have is the canonical way to do it: have an extern declaration in the header file, and define the variable in the .c file.
my array will be an undefined symbol in worker.c
No, it won't. Your code will compile and link just fine.
I often put the definition in the header (this is frowned upon, I know).
It keeps the definition and declaration close together, which is a Good Thing.
/* file.c */
#define FILE_C 1
#include "file.h"
.
/* file.h */
#ifndef FILE_H
#define FILE_H 1
#define BIG_SIZE 13
#if FILE_C
char the_array[BIG_SIZE];
#else
extern char the_array[BIG_SIZE];
#endif
#endif /* FlLE_H */
.
/* other_file.c */
#include "file.h"
There is no risk of doing it wrong: the linker will complain if you do it wrong.
BTW a similar way to basically do the same, but maybe a bit more readable, is:
/* file.h */
#ifndef FILE_H
#define FILE_H 1
#if FILE_C
#define EXTERN /**/
#else
#define EXTERN extern
#endif
#define BIG_SIZE 13
EXTERN char the_array[BIG_SIZE];
...
#undef EXTERN
#endif /* FlLE_H */
Having one declaration (extern...) in each translation unit and exactly one definition is the most elegant way to do this.
So leave the extern char important_array in the header and char important_array in one of the .c files.
Create a new function at utilities.c called something like "get_important_array" that just returns a pointer to array and put the prototype at utilities.h. After that, when you put the utilities.h at worker.c you'll have important_array access in a simple, and organized way.

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

shared global variables in C

How can I create global variables that are shared in C? If I put it in a header file, then the linker complains that the variables are already defined. Is the only way to declare the variable in one of my C files and to manually put in externs at the top of all the other C files that want to use it? That sounds not ideal.
In one header file (shared.h):
extern int this_is_global;
In every file that you want to use this global symbol, include header containing the extern declaration:
#include "shared.h"
To avoid multiple linker definitions, just one declaration of your global symbol must be present across your compilation units (e.g: shared.cpp) :
/* shared.cpp */
#include "shared.h"
int this_is_global;
In the header file write it with extern.
And at the global scope of one of the c files declare it without extern.
In the header file
header file
#ifndef SHAREFILE_INCLUDED
#define SHAREFILE_INCLUDED
#ifdef MAIN_FILE
int global;
#else
extern int global;
#endif
#endif
In the file with the file you want the global to live:
#define MAIN_FILE
#include "share.h"
In the other files that need the extern version:
#include "share.h"
You put the declaration in a header file, e.g.
extern int my_global;
In one of your .c files you define it at global scope.
int my_global;
Every .c file that wants access to my_global includes the header file with the extern in.
If you're sharing code between C and C++, remember to add the following to the shared.hfile:
#ifdef __cplusplus
extern "C" {
#endif
extern int my_global;
/* other extern declarations ... */
#ifdef __cplusplus
}
#endif
There is a cleaner way with just one header file so it is simpler to maintain.
In the header with the global variables prefix each declaration with a keyword (I use common) then in just one source file include it like this
#define common
#include "globals.h"
#undef common
and any other source files like this
#define common extern
#include "globals.h"
#undef common
Just make sure you don't initialise any of the variables in the globals.h file or the linker will still complain as an initialised variable is not treated as external even with the extern keyword. The global.h file looks similar to this
#pragma once
common int globala;
common int globalb;
etc.
seems to work for any type of declaration. Don't use the common keyword on #define of course.
There is a more elegant way to create global variables.
Just declare the variables as static inside a ".c" source file and create set/get functions.
The example below I use to override malloc, realloc and free functions during memory allocation tests.
Example:
memory-allocator.h
#ifndef MEMORY_ALLOCATOR_H_
#define MEMORY_ALLOCATOR_H_
#include <stddef.h>
void std_set_memory_allocators(void *(*malloc)(size_t size),
void *(realloc)(void *ptr, size_t size),
void (*free)(void *ptr));
void std_set_reset_allocators();
void *std_malloc(size_t size);
void *std_realloc(void *ptr, size_t size);
void std_free(void *ptr);
#endif // MEMORY_ALLOCATOR_H_
memory-allocator.c
#include "memory-allocator.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
void *(*malloc)(size_t size);
void *(*realloc)(void *ptr, size_t size);
void (*free)(void *ptr);
} StdMemoryAllocator;
StdMemoryAllocator memory_allocators = {&malloc, &realloc, &free};
void std_set_memory_allocators(void *(*malloc)(size_t size),
void *(realloc)(void *ptr, size_t size),
void (*free)(void *ptr)) {
memory_allocators.malloc = malloc;
memory_allocators.realloc = realloc;
memory_allocators.free = free;
}
void std_set_reset_allocators() {
memory_allocators.malloc = malloc;
memory_allocators.realloc = realloc;
memory_allocators.free = free;
}
void *std_malloc(size_t size) {
return memory_allocators.malloc(size);
}
void *std_realloc(void *ptr, size_t size) {
return memory_allocators.realloc(ptr, size);
}
void std_free(void *ptr) {
memory_allocators.free(ptr);
}
The struct static struct StdMemoryAllocator_s memory_allocators is started automatically when the application starts, and it point to the default C memory allocators.

Resources