1

I was looking at a C header file which at some point had the following declaration(the code is written by a competent person so I assume t's not a mistake.

#ifndef _BLABLA_
#include <stdint.h>

external uint32 x;

#endif

Why is the variable declared external? As long as it's defined together with a library, we can be sure it's not going to be used within another function. Is it just coding style?

bsky
  • 19,326
  • 49
  • 155
  • 270

2 Answers2

1

the extern keyword is to make a variable shared across compilation units:

here is the shortest example I could work out to show off how it works:

blabla.c:

int x = 1;

main.c:

#include <stdio.h>
extern int x;

int main() {
    printf("%d\n", x);
    return 0;
}

compilation:

gcc -o main main.c blabla.c

N.B.: it's only an example to show off how it's working, but it's not good development practice.

And I totally agree with @dasblinkenlight:

using globals is bad practice, making it really hard to read and understand one's code (even if it is your code you're reading 6 months after). So avoid those at all costs!

Community
  • 1
  • 1
zmo
  • 24,463
  • 4
  • 54
  • 90
  • Saying that globals are bad is pretty harsh considering that lot of C usage happens in embedded world where globals are necessary. – user694733 Jan 30 '14 at 14:00
  • I wouldn't go so far as to say to avoid them at all costs. But always onsider if you need them in that way. – glglgl Jan 30 '14 at 14:07
  • @user694733 I'm actually developing *a lot* in the embedding world, and I'm fighting as much as I can the over usage of *globals* and *gotos*. It's sad that the Arduino environment has been designed so that singletons are necessarily globals whereas it could have been done differently. But Arduino is C++ and you can embed your singletons globals in namespaces. – zmo Jan 30 '14 at 15:09
1

No, it is not a coding style. Unless the variable declared external, the compiler is going to consider the declaration a definition of that variable as well. Definitions of globals must be unique; if you include a header without an extern in several translation units (i.e. more than one .C file) you are going to get linker errors.

we can be sure it's not going to be used within another function.

Actually, the point of declaring that variable extern is to let any function that included that header use the variable x: variables like that are considered global. Using lots of globals is a common cause of maintenance headaches, so one should be very careful to introduce them only when they are absolutely necessary.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • "Definitions of globals must be unique; if you include a header without an `extern` in several translation units (i.e. more than one .C file) you are going to get linker errors." Here you forget about the [tentative definitions](http://stackoverflow.com/questions/3095861/about-tentative-definition). – glglgl Jan 30 '14 at 14:08
  • @glglgl If I remember it right, tentative definitions work within a single translation unit. If there is no definition that's definitely a definition (i.e. because it has an initializer) then the tentative definition becomes a real definition. Putting them in two translation units causes link errors. – Sergey Kalinichenko Jan 30 '14 at 14:15
  • a.c: `int tent; int * a(void) { return &tent; }` - b.c: `int tent; int * b(void) { return &tent; }` - m.c: `#include int * a(); int * b(); int tent = 4; int main() { printf("%p %p %p %d\n", a(), b(), &tent, tent); }` -> `0x804a020 0x804a020 0x804a020 4` - so at least gcc accepts it. – glglgl Jan 30 '14 at 14:22
  • But you may be right - [here](http://www.velocityreviews.com/forums/t598446-tentative-definition-versus-external-linkage.html) they talk about it being UB. – glglgl Jan 30 '14 at 14:27