1

I know that extern is very important with variables as per this question What's the difference between using extern and #including header files? and I totally see the point and rationale of using extern variable.

But I can't still digest the idea behind extern function, I know how it works and linking and all of that, but wouldn't it be the same if we have the function defined in a header file?

I can only think of the benefit of using dynamic-link library so we don't have to build our application each time the library changes, but why I go out of my way and use extern with static-link library instead of just include the header file.

UPDATE:

I know the difference between defintion and declaration.

Omar Khalid
  • 324
  • 1
  • 3
  • 15
  • 3
    Note: all functions are by default `extern` linkage, unless it's limited by mentioning `static` explcitly, then it's limited to file scope. What any of these have to do with a forward declaration (i.e., putting in header file)? – Sourav Ghosh Sep 25 '20 at 07:14
  • You seem to be confusing the terms 'define' and 'declare' -- they are not the same thing and have very specific meanings in C and C++ – Chris Dodd Sep 25 '20 at 07:20
  • @SouravGhosh This is not my point, my point is that why I would use `extern` with static library for example instead of just include it, assuming that we already have `.h` and `.c` files for the definition of that function. – Omar Khalid Sep 25 '20 at 07:50
  • See: https://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration Static vs dynamic library is mostly a red herring; don't chase it. Headers (in C) normally declare things — types, variables, functions, etc — and do not define them. The definitions are provided separately. C++ has header-only libraries which do provide the implementation. These are very rare in C; the language doesn't support them well. – Jonathan Leffler Sep 25 '20 at 07:53
  • @JonathanLeffler I guess you are right that it is red herring. – Omar Khalid Sep 25 '20 at 08:00
  • 1
    I don't really understand the question. Whether to declare a function in a header or somewhere else, and whether to declare it `extern` or not, are separate questions, aren't they? – Kevin Boone Sep 25 '20 at 08:22
  • @KevinBoone I'm asking what is the point of using `extern` function when you can accomplish the same end result with other methods. I guess it is more of a design question than anything else. – Omar Khalid Sep 25 '20 at 08:44
  • 2
    You don't usually need to use `extern` on function declarations, wherever they are. People often do, for reasons of style, or out of habit. The Linux kernel headers are full of `externs`. – Kevin Boone Sep 25 '20 at 08:51
  • Okay that is what I wanted to hear that people use it out of habit, I thought that there are some other reasons. – Omar Khalid Sep 25 '20 at 09:17
  • The question is unclear. My best interpretation is it is asking the difference between declaring a function oneself, as with a declaration such as `extern void foo(int x);`, versus including a header that declares the function. There is no difference in the resulting declaration; a declaration brought in via `#include` has the same effect as a declaration in the source file itself. Practical differences include that a header typically declares or defines other identifiers, which might be undesired in a particular source file, and that a declaration manually inserted in a source file… – Eric Postpischil Sep 25 '20 at 11:06
  • … may have typographical errors that are not caught, whereas errors in a header file are more likely to be caught, both because it is more widely used and because it is common practice to include it in the source file that defines the things the header declares, which would result in the compiler reporting discrepancies. However, the question explicitly asks about a function **defined** in a header file, notwithstanding the updated statement from the OP asserting they know the difference between a definition and a declaration. A function definition in a header is unusual… – Eric Postpischil Sep 25 '20 at 11:07
  • … and comparing a definition in a header to a declaration in a source file would be a radical change in the question. Regardless, the mention of a dynamic-link library appears irrelevant, as external functions can be linked either statically or dynamically, and whether they are declared in source files or headers is irrelevant to this. – Eric Postpischil Sep 25 '20 at 11:09
  • 1
    (a) Edit the question to clarify whether declarations and/or definitions are being asked about. If definitions in header files are not being asked about, remove mention of definitions. (b) Edit the question to add examples. (c) Edit the question to remove the phrase “`extern` function.” I think at that point, you are asking about a ”function declaration using `extern`.” (c) State what difference you think there is between a dynamically linked library and a statically linked library that is relevant to this. – Eric Postpischil Sep 25 '20 at 11:13

2 Answers2

2
  1. Header files are added to your source .c code in the preprocessing. The C compiler compiles one large file with the all the header files added to this file. https://godbolt.org/z/Eo3n1Y

  2. Providing in your source file the same function prototypes and extern object declarations as in the .h files will have the same effect.

  3. extern used with variable shows the compiler that variable is defined somewhere in the project. It can be later in the same compilation unit (source file) (https://godbolt.org/z/4vM1of) or in another. The access will be resolved during the linking.

  4. functions are extern by definition. Modern C require function prototypes if the function was not defined before the place where it is called or is defined in other compilation unit. https://godbolt.org/z/d91P6q

0___________
  • 60,014
  • 4
  • 34
  • 74
-2

Prerequisite for understanding this: study the difference between function declaration and function definition.

I know that extern is very important with variables

This is not true. extern is an almost superfluous language feature with very limited use. Properly designed programs don't need it - it is only used in very specialized scenarios. If you find yourself using it for everyday programming, it means that your program design is flawed.

But I can't still digest the idea behind extern function, I know how it works and linking and all of that, but wouldn't it be the same if we have the function defined in a header file?

Indeed it would be the same as having the function declared in a header file. Function declarations such as void func (void) are also implicitly extern, you could as well type extern void func (void); and that's 100% equivalent. The correct way to write programs is to provide function declarations in a header file.

You most likely don't need to use extern anywhere at all.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • How about dynamic linking? I guess `extern` there is a must. – Omar Khalid Sep 25 '20 at 07:47
  • 1
    I totally disagree in case of variables. – Klaus Sep 25 '20 at 07:48
  • @OmarKhalid DLLs are loaded in run-time through API calls, `LoadLibrary` etc on Windows. You only need a header with the function declarations. – Lundin Sep 25 '20 at 07:51
  • @Klaus Yes I agree with you, I can think of many situations that needs `extern` variables. – Omar Khalid Sep 25 '20 at 07:52
  • @Klaus Good for you! Any particular reason why? Or do you simply adore spaghetti programming? – Lundin Sep 25 '20 at 07:52
  • 1
    I've worked with C programming and system design for over 20 years, and I've only used `extern` once or twice in all that time. With that experience, I can confidently challenge you to provide an example where you think you need `extern` and I can point out the flaws in your overall program design. Sure there are a few specialized cases, as mentioned in the answer, non-standard microcontroller register maps for memory-mapped hardware registers could sometimes use it. That's about the only valid scenario I know of. – Lundin Sep 25 '20 at 07:54
  • 2
    Having global state representing global objects is, for lack of better word, reasonable. stdin and stdout, and their c++ counterparts, comes to mind. – Passer By Sep 25 '20 at 07:57
  • @Lundin Don't get angry by people on the internet, I "can" see your point. But I see it used A LOT in a very high-profile projects. – Omar Khalid Sep 25 '20 at 08:00
  • I've seen very large systems (takes 10 minutes just to link) having linking problems when the code author have dropped extern, saying that it has always worked without it. Just stick the extern in and linkage goes through without any problems. It seems to work without it on smaller systems (<10s to link). – cup Sep 25 '20 at 08:08
  • 2
    @Lundin *`I've worked with C programming and system design for over 20 years, and I've only used extern once or twice in all that time.`* this question is not about the good programming practices and how bad or good the global objects are, but about the language itself. – 0___________ Sep 25 '20 at 08:10
  • @PasserBy Err, no. `stdio.h` is one of the most horribly designed libraries ever written for any programming language, so don't go look for inspiration there. There is absolutely no reason to expose the `stdout` etc variables to the caller, a plain enum would have worked just as fine. Or using a different function name, imagine if they had made a function that works like `fprintf` but only writes to `stdout`... oh wait, they did. So why do we need the variable for then? Nobody knows. – Lundin Sep 25 '20 at 09:21
  • I can't seem to make precise what I mean. _"most horribly designed libraries"_ is not a fact, but your opinion. It doesn't, by virtue of having a global state, cause massive harm across the world. I'm not going to argue code design here. – Passer By Sep 25 '20 at 09:26
  • 1
    @OmarKhalid There are numerous famous, "high profile" C libraries out there, that were horribly written. The Windows API and the Unix/Linux API being two perfect examples. Just because those _products_ were successful, it doesn't mean that the were successfully because of their wonderfully written code. – Lundin Sep 25 '20 at 09:26
  • @cup So maybe don't use any form of spaghetti variables, extern or not, and refrain from tight coupling between every single module of the project? It is very rare that we need to share actual variables across modules, normally they get copied or passed by pointers to APIs. – Lundin Sep 25 '20 at 09:28
  • @P__J__ In that case it should be closed as a dupe to this: https://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files – Lundin Sep 25 '20 at 09:31
  • "Any particular reason why?" Yes: If you have global objects/Data, you have `extern` or you start to encapsulate all with some getters. E.g. loggers, IO stuff (cin/cout is also extern...). Even if they are singletons, the GetInstance() is matter of taste. SIOF can be handled without the bad sides of singletons... so it is still matter of taste. " superfluous language feature ". If you want to dictate style of programs, you can remove it. But that is only your personal opinion and your code style and not a general rule! – Klaus Sep 25 '20 at 09:32
  • @PasserBy Well yes, the reason why stdio.h has in fact already cause massive harm across the world, is not so much because of the global variables but the format strings and variadict functions, as well as plain bad APIs like `gets`. The globals in that library are mostly sprinkles upon the stinking pile of dung. And it's not just my personal opinion that the library shouldn't be used in production code, many well-known coding standards ban it. – Lundin Sep 25 '20 at 09:34
  • @Klaus The key is indeed not to have global objects but only `static` file scope ones, or caller-allocated ones. And that is very much a general rule, the old "globals" debate has an overwhelming consensus against using them. – Lundin Sep 25 '20 at 09:37
  • "overwhelming" :-) I agree with most of all your aspects, but not with these kind of generalization. There are good reasons for all the hints and best practice guide lines. And one of these guide lines is: Never tell us there is a general rule! It is good to know much rules, but it is much more important to know *why* the rule exist. – Klaus Sep 25 '20 at 09:55
  • @Klaus Well you can go count votes here, for example: https://stackoverflow.com/questions/484635/are-global-variables-bad. Looking at the top-voted answer, 99.3% of all 269 voters agreed with it. As for best practice rules, this is the flood of beginner questions also known as SO. Beginners need to be told: do this, don't do this, period. When they have programmed for some 5+ years then they can start to question those rules. It is not helpful to give them an answer just stating "this is how you use `extern`" with no disclaimers, doing so turns beginners into worse programmers. – Lundin Sep 25 '20 at 10:05
  • I see the question you refer is simply closed because it is opinion based! "Beginners need to be told: do this, don't do this, period." Wow! You want to make them stupid robots simply coding without thinking? Sorry, not my idea of education. There are also tons of examples of good working code with globals. Again: cin/cout is working well. I believe we simply stay both on our opinions here :-) – Klaus Sep 25 '20 at 10:19
  • @Klaus It's called pedagogy. The problem is that C is such a horrible patchwork of broken and dangerous things, that you cannot easily explain all the possible problems to a beginner. Take something seemingly trivial like `char a = b + c;`. In order to fully understand all potential problems in this code, you need to understand implementation-defined signedness of char, portability issues, symbol table issues, integer overflow, integer promotion & arithmetic conversion. It's too much to take in for a complete beginner, just tell them "you should use int instead". – Lundin Sep 25 '20 at 10:38