1

I read that the extern keyword is implicit in the context of functions, so unless you specify otherwise using the static keyword (which if I'm not mistaken is basically a completely separate concept from the static that variables employ—they just share a keyword), they are visible to all object files. This makes sense; having the declarations be implicitly external, while technically unnecessary when the declarations are in the same file as the definition, is useful because the programmer doesn't have to type extern every time they want to use a function out of its defining file, which is more often the case than not. What seems odd to me is that it is implicit for the declarations and the definition.

With a variable, I don't need to include an extern for the definition, and in fact, while I can do this without error, my compiler gives me a warning for it.

For example, I can have mylib.h:

int var = 5;

//it isn't necessary to write this as
//extern int var = 5;
//my compiler even warns against it

and test.c

#include "mylib.h"

extern int var;

I would normally assume the implicit extern for functions to be the same, that is, if I defined int func(int par) in mylib.h, there would not be an implicit extern before it, but there would be an implicit extern for any declaration of it (such as if I declared it for use in test.c).

It also doesn't make much sense from the perspective of the extern keyword being used as a way of telling the compiler to look elsewhere for the definition, when the definition would never be external of the file it is in.

I feel like I'm missing something here.

thepufferfish
  • 381
  • 2
  • 15
  • 3
    Maybe I misunderstand your question but it seems to me that you are doing this the wrong way. Putting `int var` into an h-file and putting `extern int var` in th c-file is not the usual way. Not sure these to Qs are dupes but I think you'll find the needed info by reading: https://stackoverflow.com/q/1433204/4386427 and https://stackoverflow.com/q/1410563/4386427 – 4386427 Nov 11 '20 at 07:12
  • 3
    If you write `int var = 5;` in `mylib.h`, then that defines the variable. In any given program, only one file can include `mylib.h` — if more than one file includes the header, you get multiply-defined errors. With GCC 10.x, by default, even if you write `int var;` in a header (rather than `extern int var;`), you will end up with multiple definition errors — though older versions of GCC did not do that by default. – Jonathan Leffler Nov 11 '20 at 07:13
  • 3
    For further discussion, see: [How do I use extern to share variables between source files?](https://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files/1433387?r=SearchResults&s=1|186.2296#1433387) and [When to use extern “C” in C++?](https://stackoverflow.com/questions/1292138/when-to-use-extern-c-in-c?r=SearchResults&s=2|123.2376) and [When to use extern “C” in simple words?](https://stackoverflow.com/questions/2796796/when-to-use-extern-c-in-simple-words?r=SearchResults&s=3|121.4664) – David C. Rankin Nov 11 '20 at 07:18
  • 1
    The `static` keyword for both variables and functions limits the visibility of the named object. There are differences — you can have static variables inside functions, for example. But the concepts are sufficiently similar that saying _"[`static` applied to functions] is basically a completely separate concept from the `static` that variables employ"_ is an overstatement at least. – Jonathan Leffler Nov 11 '20 at 07:19
  • I'm going off of *Beginning C 5th Ed.* by Ivor Horton, from apress. It gives the example of `int number = 0; double in_to_mm = 2.54;` which it places in one file, and the source file accessing the global variables uses `extern int number; extern double in_to_mm;` – thepufferfish Nov 11 '20 at 07:20
  • @thepufferfish In your comment about the book you write: "... which it places in one file..." Are you sure that is in an h-file? If so it's very strange... but if it's in a c-file, it's ok – 4386427 Nov 11 '20 at 07:24
  • @4386427 I took a screenshot of the book page https://imgur.com/a/esV4Wpa – thepufferfish Nov 11 '20 at 07:26
  • If you are a beginner you should avoid `extern` entirely. There is very limited use for the keyword in properly designed programs. A few special cases exist, but they are very specialized. – Lundin Nov 11 '20 at 07:26
  • If the definitions with the initializers are shown in a header file, then throw the book away — now! If it can't get that right, you don't know what else it is mis-teaching you! It would be fine if the definitions with initializers are in a source file, not a header. But all the source files referencing or defining those variables should include the header that declares the variables (`extern int number; extern double in_to_mm;`).To ensure proper cross-checking, the header should be included by the source file that defines and initializes those variables as well as by those that reference it. – Jonathan Leffler Nov 11 '20 at 07:26
  • 1
    @thepufferfish From the picture you linked it's obvious that the book is talking about two different source files (aka c-files). It's not talking about one h-file and one c-file. – 4386427 Nov 11 '20 at 07:28
  • 1
    I would argue that making functions externally visible by default in C was a mistake. It would, IMO, be far better if the default was `static` and you had to explicitly mark the function as visible outside the source file. – Jonathan Leffler Nov 11 '20 at 07:28
  • @4386427 I guess I must have falsely assumed that header files were also okay for this. That and I tested the `extern int var` thing out and the gcc compiler had no error or warning about my putting the definition in the header without `extern` but including it with the declaration in the source file. Looking at sravs' answer, I guess it's because I only had one header and one source file in my test. – thepufferfish Nov 11 '20 at 07:35
  • @4386427 I am a little confused from the perspective of, even using just two different source files, the definition seems to lack an `extern` and the declaration has one, while in sravs' answer, it looks like it is the other way around where the definition has the keyword and the declarations omit it. – thepufferfish Nov 11 '20 at 07:40
  • 1
    @thepufferfish You don't use `extern` in **definitions**. You use `extern` in **declarations**. The declaration simply says: This variable is defined in some other compilation unit, i.e. in another c-file. The use of `extern` declaration in **h-files** is simply to avoid to write the same stuff again and again in multiple c-files. – 4386427 Nov 11 '20 at 07:44
  • @4386427 Oh, okay, I see. I misread sravs' program where my brain again kind of assumed that the definition would go into the header, even though that would cause the conflict of global variables that their answer was warning against anyways – thepufferfish Nov 11 '20 at 07:46
  • @Lundin I see. I sort of assumed that it was more of an 'advanced beginner' concept. Basically, I'm familiar with the absolute basics of stuff like variables, functions, arrays, pointers, loops, conditions, etc. and I'm trying to figure out what comes next. – thepufferfish Nov 11 '20 at 07:50
  • @JonathanLeffler regarding the `static` keyword, I thought that in the context of variables it is used for the purpose preventing the destruction of the variable between instances of running a function and that 'visibility' was more a concept of scope, where it depends on what 'level' of code block you put the variable in (i.e. loops, functions, conditions, etc.). – thepufferfish Nov 11 '20 at 07:51
  • 1
    @thepufferfish Read https://stackoverflow.com/questions/33034503/static-variable-file-scope – 4386427 Nov 11 '20 at 07:59
  • @JonathanLeffler Anyways, regardless of whether the default for functions is to implicitly declare them as `static` or `extern`, and regardless of whether it was a mistake or not; I do still wonder, why would the definitions have the implicit `extern`? – thepufferfish Nov 11 '20 at 08:07
  • @4386427 You said you don't use `extern` for definitions, when we were talking about variables. I'm still kind of confounded by the implicit use in function definitions. – thepufferfish Nov 11 '20 at 08:09
  • @thepufferfish Well, your real question, i.e. "why are functions implicit extern" can probably only be answered by the inventors of C. There is no technical reason as far as I can see. My guess is that they preferred it like that in order to avoid the need of writing `extern` in a lot of h-files. – 4386427 Nov 11 '20 at 10:41

1 Answers1

2

If you use int x = 10; in any header file, then you are entering into trouble, because if you include the same header file in any other file (.c or .h) that is linked with test.c then you will get an error redefinition of variable x.

You can try that for yourself.

So always keep extern int x; in a header file, and define it int x = 10; in any .c file.

So, in this case, if you include the header file in multiple places, it is fine, because the header file only has a declaration and you can declare the same variable in multiple places without any problem.

you can try this sample program to test the error multiple definition of `global_value'

test.h

extern int global_value;

test.c

#include <stdio.h>
#include "test.h"
int global_value = 10;

int test_func()
{
        printf("golbal_value = %d", global_value);
        global_value = 20; // changed here, reflect in main after test_func call
}

main.c

#include <stdio.h>
#include "test.h"
int main()
{
        test_func();
        printf("global_value = %d\n", global_value);
        return 0;
}

the above program works perfectly. to get the error bring that extern int global_value; to test.c and int global_value = 10; to test.h and compile all together gcc test.c main.c

csavvy
  • 763
  • 4
  • 13
  • Thank you, this really helps me get a better understanding of why headers should not contain global variable definitions. So far as I understand, because headers are appended to the source file in preprocessing you basically could run into trouble with having multiple source files each defining that global variable, confusing the compiler. I guess you could theoretically have the same issue if you included the header twice in one source file, if you don't have inclusion guards; though I guess if your header doesn't have inclusion guards, that's a big problem to begin with. – thepufferfish Nov 11 '20 at 08:05
  • So, I just thought of something. If there is the issue of global variables conflicting with themselves when defined in header files, does that mean that, given the implicit `extern` in functions, unless you define a function as `static` in a header, it would have the same issue? That is, it is better to declare the function in a header, but it is likely to cause issues if it is defined there? – thepufferfish Nov 12 '20 at 01:40
  • generally we dont declare `static` functions in header files because we want to use the static functions in the one single `.c` not out side of the file. so we declare them in `.c` itself above all other statements. – csavvy Nov 12 '20 at 03:49