0

Let's suppose that I write some functions in a file, that we'll call foo.c. This is foo.c:

int d;

typedef int bar;

int foo(int a, int b){
 ...
}

void boo(){
 ...
}

char *test(){
 ...
}

Now, boo is a function used only inside foo.c, while foo(), test(), d, and Bool will need to be able to get called inside other files.

In order to do that, I know that I have to create a foo.h file and write it like this:

extern int d;
extern typedef int bar;
int foo(int a, int b);
char *test();

then #include "foo.h" in the foo.c file, and whenever I want to use the types and functions defined in foo.c, I have to include both foo.hand foo.cin the file in which I wanna use foo.c functions and types.

So foo.c in the end would look like this:

#include "foo.h"

int d;

typedef int bar;

int foo(int a, int b){
 ...
}

void boo(){
 ...
}

char *test(){
 ...
}

Here are my questions.

Q1. Is this how you actually do it? Since foo.h is already included in foo.c, wouldn't it be sufficient to include only foo.c in the file in which I want to use its functions? Can't I just directly define the functions inside of the foo.c file, not using the foo.h file at all?

Q2. Do you actually have to put the extern in front of typedefs in the foo.h file?

Q3. Let's say that in foo.c I use some standard C libraries like string.h and math.h . Where should I include them? Directly in the foo.c file, in the foo.h file or in both? Are #ifndef instructions necessary? If so, how do you use them correctly?

Q4. After writing the foo.c and foo.h file, am I all ready to go? Like, I don't need to compile them or anything, right? I can just #include them wherever I need just like that?

Q5. Somewhere else I've read that if I want to use a custom library these are the steps that I need to follow:

  • define the interface (foo.h)
  • write foo.c #include ing foo.h
  • creating an object file like this gcc -o foo.o -c foo.c
  • including foo.h in the program in which I want to use foo.c functions
  • linking the object file like this gcc my_proj.c foo.o

Are these steps actually necessary? Because I haven't seen them mentioned anywhere else. Why do I only need to include foo.h in the file in which I want to use foo.c functions? What exactly is an object file?

Thanks for your time and sorry if this is a bit lengthy

  • 4
    `wouldn't it be sufficient to include only foo.c` - never include C files (i.e., files with actual code), only H files (i.e., files with function declarations and/or preprocessor definitions). – goodvibration May 24 '19 at 13:18
  • 2
    It's not a good idea to `typedef` `Bool` as an `int` – alx - recommends codidact May 24 '19 at 13:20
  • @goodvibration why is that? Also wouldn't I need to include both of them anyways? If I included only foo.h, how would the program see what each function does? foo.c can see foo.h content, but foo.h can't see foo.c, right? –  May 24 '19 at 13:20
  • @CacahueteFrito it was just an example, the question would be the same if I typedefs a data structure or anything really –  May 24 '19 at 13:22
  • 2
    **"I don't need to compile them or anything, right?"** Right, as long as your only purpose is to write C source code, and never execute it. Or maybe I understood wrong? – virolino May 24 '19 at 13:22
  • 2
    You should read a little bit about the difference between compilation and linking. ... and translation units. – Swordfish May 24 '19 at 13:22
  • I think that this question is way too broad to be only one question. – virolino May 24 '19 at 13:23
  • @virolino agreed – Swordfish May 24 '19 at 13:24
  • 2
    @FoxyIT Well, then it's one of the worst examples one could think of. Please call it `typedef int bar;` or anything other than bool – alx - recommends codidact May 24 '19 at 13:24
  • @virolino I would want to compile only the final code. Like, let's say I included `foo.h` in proj.c... if I compiled prog.c only, would everything still work correctly or would I need to do something beforehand to the foo.h and foo.c files? –  May 24 '19 at 13:25
  • 1
    @FoxyIT: while interesting, the topic you address is significantly above your programming knowledge level. Why? It should be obvious why "It's not a good idea to typedef Bool as an int" - yet you have questions about it. No answer here will do you any good - the foundation you have is not yet solid enough for it. – virolino May 24 '19 at 13:30
  • @virolino I actually meant to `typedef int Bool` and just got confused while writing everything down –  May 24 '19 at 13:32
  • @FoxyIT: hint - Bool should be an enum ;) – virolino May 24 '19 at 13:34
  • @virolino yea I've read that's a better way of doing it but I didn't think that typedefing Bool as an int is inherently wrong, there's better way of doing it of course but it just had to serve me as a quick example –  May 24 '19 at 13:37
  • @FoxyIT it IS inherently wrong. `typedef _Bool bool;` is the only right way for it. If you're using a dinosaur of a compiler that only has C89 and doesn't have `` as an extension (even Visual Studio should have `bool`), please change your compiler. The problem is that a true value should be read as `1` always, while your `Bool` will store true as a non-zero value. – alx - recommends codidact May 24 '19 at 13:46
  • [`extern typedef`!? seriously?](https://godbolt.org/z/NHqFbu) Access to a C compiler would be of help here. – Antti Haapala -- Слава Україні May 24 '19 at 14:03
  • Functions that don't have parameters should be `(void)` and not `()`. Example: `char *test(void);`. Compile with high warnings to avoid those errors. In GCC it should be this way `gcc -std=c17 -Wpedantic -Wall -Wextra -Werror -c foo.c -o foo.o` – alx - recommends codidact May 24 '19 at 14:03
  • 1
    since the function `boo()` is never to be called outside the file: `foo.c`, the prototype should have the modifier `static` – user3629249 May 24 '19 at 15:01

2 Answers2

3

Q1. Is this how you actually do it? Since foo.h is already included in foo.c, wouldn't it be sufficient to include only foo.c in the file in which I want to use its functions?

You just don't include .c files. In your case, foo.c and the other files are separate compilation units which get linked together in the end.

Q2. Do you actually have to put the external in front of typedefs in the foo.h file?

No, typedefs don't need extern.

Q3. Let's say that in foo.c I use some standard C libraries like string.h and math.h . Where should I include them? Directly in the foo.c file, in the foo.h file or in both? Are #ifndef instructions necessary? If so, how do you use them correctly?

If you need these files in the .h as well, you include them there (e. g. for types used in function prototypes). If you need them only in your .c, include them there.

Q4. After writing the foo.c and foo.h file, am I all ready to go? Like, I don't need to compile them or anything, right? I can just #include them wherever I need just like that?

You can compile them in order to get something callable. If you don't compile your program, you cannot use it. Or do I understand you wrong?

Q5. Somewhere else I've read that if I want to use a custom library these are the steps that I need to follow:

[snip]

Indeed, this is one way to go. The steps 1, 2 and 4 cannot be omitted for obvious reasons. But you can execute step 3 and 5 together by doing

gcc my_proj.c foo.c

This compiles the given files and then links them together in one call.

Why do I only need to include foo.h in the file in which I want to use foo.c functions?

That's because the resulting object file contains information for the linker about which function it needs from other object files.

What exactly is an object file?

It is what results from compiling one source file. If you link several object files together, you get a running executable.

In other words: An object file is the compiled version of a source file. It "provides" the identifiers needed by other object files, and it "requires" other identifiers provided by other files. Linking them together means that the required and the provided objects are connected in an appropriate way so that the program can run.

Example: You have a foo.c which defines the functions foo and test. Then you have a main.c which makes use of these functions and provides a function main. In the end, they are linked together and combined with the startup code which is needed to start a program and which calls main(). The points in main() where foo() and test() are called respectively are marked in a special way so that the linker can put the actual call address there.

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • so basically including only the foo.h file is sufficient because later on when linking the proj.c file with the foo.o file, the program gets to see what each function definition actually does? when linking the two files, wouldn't foo.h get defined twice though as it is already defined in foo.c? –  May 24 '19 at 13:39
  • Also what if I include some standard C libraries in the foo.c file and then re-include them in the proj.c file... would I encounter any problems? –  May 24 '19 at 13:42
  • 3
    @FoxyIT Including a file only means that its contents are made known in the including file. That's why you only have declarations in .h files, no definitions. (See [here](https://stackoverflow.com/q/1410563/296974) the difference of both.) If you follow this principle, no problems of this kind are to be expected. – glglgl May 24 '19 at 13:45
1

Q1. Is this how you actually do it?

No

Since foo.h is already included in foo.c, wouldn't it be sufficient to include only foo.c in the file in which I want to use its functions?

You should only include .h files; both in the file that defines them, and in the ones that use them. As an extra, that include should be the first one in the file that defines the functions, but in the files that use them, it should go after the rest (standard headers, other packages' headers, ...); the reason for this is to detect errors easily.

Can't I just directly define the functions inside of the foo.c file, not using the foo.h file at all?

Usually, no. Only static inline functions should do that.

Q2. Do you actually have to put the extern in front of typedefs in the foo.h file?

No: typedef int foobar_t;

Q3. Let's say that in foo.c I use some standard C libraries like string.h and math.h . Where should I include them?

In the file that needs them (foo.c). Include in every file only the headers that it needs. No more; no less.

Directly in the foo.c file, in the foo.h file or in both?

foo.c

Are #ifndefinstructions necessary? If so, how do you use them correctly?

Yes:

// foo.h
#ifndef FOO_H
#define FOO_H

Here go all the contents of foo.h

#endif     /* foo.h */

Q4. After writing the foo.c and foo.h file, am I all ready to go? Like, I don't need to compile them or anything, right? I can just #include them wherever I need just like that?

You need to compile foo.c into foo.o (object file) and then you probably would like to do a static library (.a) or a dynamic one. You can include it wherever you want, but you will need to prepare your Makefile to do so.

Q5. Somewhere else I've read that if I want to use a custom library these are the steps that I need to follow:

define the interface (foo.h)

write foo.c #include ing foo.h

creating an object file like this gcc -o foo.o -c foo.c

including foo.h in the program in which I want to use foo.c functions

linking the object file like this gcc my_proj.c foo.o

Are these steps actually necessary?

Yes

Because I haven't seen them mentioned anywhere else. Why do I only need to include foo.h in the file in which I want to use foo.c functions?

Read more about compiling and linking.

What exactly is an object file?

A compiled file. Many of them are usually linked together to produce the executable file.

  • Regarding the answer to this question: `Are #ifndefinstructions necessary? If so, how do you use them correctly?` that has to be done in the foo.h file, right? not the proj.c. `and then you probably would like to do a static library (.a) or a dynamic one. You can include it wherever you want, but you will need to prepare your Makefile to do so.` Also I didn't really get this part –  May 24 '19 at 13:50
  • 1
    @FoxyIT 1) Yes, in all `.h` files and only in `.h` files – alx - recommends codidact May 24 '19 at 13:57
  • @FoxyIT 2) You shouldn't worry about it yet. Link the object files manually, which is easier, and when you have played enough with that, and fully understand how to use them, then you can try to do a library and ask here if you have any questions. :) – alx - recommends codidact May 24 '19 at 13:59