Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

75%
+4 −0
Q&A Extern keyword in C and proper way to use extern variables in embedded systems

And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them? Function declarations default to being extern. If you don't specify any st...

posted 2mo ago by alx‭  ·  edited 2mo ago by alx‭

Answer
#4: Post edited by user avatar alx‭ · 2026-07-19T11:13:24Z (2 months ago)
tfix
  • > And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them?
  • Function declarations default to being `extern`. If you don't specify any storage-class specifiers, a function prototype is `extern`.
  • This is specified in C23 in 6.2.2p5:
  • > <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#subsection.6.2.2>
  • >
  • > If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier **extern**.
  • Function definitions are only those that have a function body, so the storage-class specifier is independent.
  • In the case of variables, it's different.
  • > As far as I understand it, declaring variables as `extern` in pins.h makes them visible to source files that include pins.h, and I need not define them again.
  • You need not _declare_ them again. There's a difference between declarations and definitions.
  • With functions, it's more obvious: a function prototype declares a function, but only a function definition (those that have a function body) define a function.
  • With variables, it's different: automatic variables and `static` variables are not declared; they're directly defined. With `extern` variables, you can declare them without defining them.
  • The way to define a variable with external linkage is to declare it in file scope without any storage class specifiers.
  • The way to declare a variable with external linkage is to declare it in file scope with the `extern` storage-class specifier.
  • > But to be honest, I'm not sure why I need extern in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • To disambiguate between a declaration and a definition. The definition is what assigns some storage to the name, and also the initial value.
  • > I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • Because by removing it, you're defining the variable in more than one translation unit, and thus assigning a different storage to the same variable name in different TUs. There must be unambiguous storage for any given variable.
  • > And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them?
  • Function declarations default to being `extern`. If you don't specify any storage-class specifiers, a function prototype is `extern`.
  • This is specified in C23 in 6.2.2p5:
  • > <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#subsection.6.2.2>
  • >
  • > If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier **extern**.
  • Function definitions are only those that have a function body, so the storage-class specifier is independent.
  • In the case of variables, it's different.
  • > As far as I understand it, declaring variables as `extern` in pins.h makes them visible to source files that include pins.h, and I need not define them again.
  • You need not _declare_ them again. There's a difference between declarations and definitions.
  • With functions, it's more obvious: a function prototype declares a function, but only a function definition (those that have a function body) defines a function.
  • With variables, it's different: automatic variables and `static` variables are not declared; they're directly defined. With `extern` variables, you can declare them without defining them.
  • The way to define a variable with external linkage is to declare it in file scope without any storage class specifiers.
  • The way to declare a variable with external linkage is to declare it in file scope with the `extern` storage-class specifier.
  • > But to be honest, I'm not sure why I need extern in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • To disambiguate between a declaration and a definition. The definition is what assigns some storage to the name, and also the initial value.
  • > I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • Because by removing it, you're defining the variable in more than one translation unit, and thus assigning a different storage to the same variable name in different TUs. There must be unambiguous storage for any given variable.
#3: Post edited by user avatar alx‭ · 2026-07-19T11:12:58Z (2 months ago)
tfix
  • > And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them?
  • Function declarations default to being `extern`. If you don't specify any storage-class specifiers, a function prototype is `extern`.
  • This is specified in C23 in 6.2.2p5:
  • > <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#subsection.6.2.2>
  • >
  • > If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier **extern**.
  • Function definitions are only those that have a function body, so the storage-class specifier is independent.
  • In the case of variables, it's different.
  • > As far as I understand it, declaring variables as `extern` in pins.h makes them visible to source files that include pins.h, and I need not define them again.
  • You need not _declare_ them again. There's a difference between declarations and definitions.
  • With functions, it's more obvious: a function prototype declares a function, but only a function declaration (those that have a function body) define a function.
  • With variables, it's different: automatic variables and `static` variables are not declared; they're directly defined. With `extern` variables, you can declare them without defining them.
  • The way to define a variable with external linkage is to declare it in file scope without any storage class specifiers.
  • The way to declare a variable with external linkage is to declare it in file scope with the `extern` storage-class specifier.
  • > But to be honest, I'm not sure why I need extern in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • To disambiguate between a declaration and a definition. The definition is what assigns some storage to the name, and also the initial value.
  • > I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • Because by removing it, you're defining the variable in more than one translation unit, and thus assigning a different storage to the same variable name in different TUs. There must be unambiguous storage for any given variable.
  • > And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them?
  • Function declarations default to being `extern`. If you don't specify any storage-class specifiers, a function prototype is `extern`.
  • This is specified in C23 in 6.2.2p5:
  • > <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#subsection.6.2.2>
  • >
  • > If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier **extern**.
  • Function definitions are only those that have a function body, so the storage-class specifier is independent.
  • In the case of variables, it's different.
  • > As far as I understand it, declaring variables as `extern` in pins.h makes them visible to source files that include pins.h, and I need not define them again.
  • You need not _declare_ them again. There's a difference between declarations and definitions.
  • With functions, it's more obvious: a function prototype declares a function, but only a function definition (those that have a function body) define a function.
  • With variables, it's different: automatic variables and `static` variables are not declared; they're directly defined. With `extern` variables, you can declare them without defining them.
  • The way to define a variable with external linkage is to declare it in file scope without any storage class specifiers.
  • The way to declare a variable with external linkage is to declare it in file scope with the `extern` storage-class specifier.
  • > But to be honest, I'm not sure why I need extern in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • To disambiguate between a declaration and a definition. The definition is what assigns some storage to the name, and also the initial value.
  • > I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • Because by removing it, you're defining the variable in more than one translation unit, and thus assigning a different storage to the same variable name in different TUs. There must be unambiguous storage for any given variable.
#2: Post edited by user avatar alx‭ · 2026-07-19T11:11:38Z (2 months ago)
pfix
  • > And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them?
  • Function declarations default to being `extern`. If you don't specify any storage class specifiers, a function prototype is `extern`.
  • This is specified in C23 in 6.2.2p5:
  • > <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#subsection.6.2.2>
  • >
  • > If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier **extern**.
  • Function definitions are only those that have a function body, so the storage-class specifier is independent.
  • In the case of variables, it's different.
  • > As far as I understand it, declaring variables as `extern` in pins.h makes them visible to source files that include pins.h, and I need not define them again.
  • You need not _declare_ them again. There's a difference between declarations and definitions.
  • With functions, it's more obvious: a function prototype declares a function, but only a function declaration (those that have a function body) define a function.
  • With variables, it's different: automatic variables and `static` variables are not declared; they're directly defined. With `extern` variables, you can declare them without defining them.
  • The way to define a variable with external linkage is to declare it in file scope without any storage class specifiers.
  • The way to declare a variable with external linkage is to declare it in file scope with the `extern` storage-class specifier.
  • > But to be honest, I'm not sure why I need extern in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • To disambiguate between a declaration and a definition. The definition is what assigns some storage to the name, and also the initial value.
  • > I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • Because by removing it, you're defining the variable in more than one translation unit, and thus assigning a different storage to the same variable name in different TUs. There must be unambiguous storage for any given variable.
  • > And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them?
  • Function declarations default to being `extern`. If you don't specify any storage-class specifiers, a function prototype is `extern`.
  • This is specified in C23 in 6.2.2p5:
  • > <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#subsection.6.2.2>
  • >
  • > If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier **extern**.
  • Function definitions are only those that have a function body, so the storage-class specifier is independent.
  • In the case of variables, it's different.
  • > As far as I understand it, declaring variables as `extern` in pins.h makes them visible to source files that include pins.h, and I need not define them again.
  • You need not _declare_ them again. There's a difference between declarations and definitions.
  • With functions, it's more obvious: a function prototype declares a function, but only a function declaration (those that have a function body) define a function.
  • With variables, it's different: automatic variables and `static` variables are not declared; they're directly defined. With `extern` variables, you can declare them without defining them.
  • The way to define a variable with external linkage is to declare it in file scope without any storage class specifiers.
  • The way to declare a variable with external linkage is to declare it in file scope with the `extern` storage-class specifier.
  • > But to be honest, I'm not sure why I need extern in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • To disambiguate between a declaration and a definition. The definition is what assigns some storage to the name, and also the initial value.
  • > I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.
  • Because by removing it, you're defining the variable in more than one translation unit, and thus assigning a different storage to the same variable name in different TUs. There must be unambiguous storage for any given variable.
#1: Initial revision by user avatar alx‭ · 2026-07-16T16:08:13Z (2 months ago)
> And with the same logic, shouldn't the function prototypes in gpio.h also be extern for my source files to see them?

Function declarations default to being `extern`.  If you don't specify any storage class specifiers, a function prototype is `extern`.

This is specified in C23 in 6.2.2p5:
> <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#subsection.6.2.2>
>
> If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier **extern**.

Function definitions are only those that have a function body, so the storage-class specifier is independent.

In the case of variables, it's different.

> As far as I understand it, declaring variables as `extern` in pins.h makes them visible to source files that include pins.h, and I need not define them again.

You need not _declare_ them again.  There's a difference between declarations and definitions.

With functions, it's more obvious: a function prototype declares a function, but only a function declaration (those that have a function body) define a function.

With variables, it's different: automatic variables and `static` variables are not declared; they're directly defined.  With `extern` variables, you can declare them without defining them.

The way to define a variable with external linkage is to declare it in file scope without any storage class specifiers.

The way to declare a variable with external linkage is to declare it in file scope with the `extern` storage-class specifier.

> But to be honest, I'm not sure why I need extern in the first place. I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.

To disambiguate between a declaration and a definition.  The definition is what assigns some storage to the name, and also the initial value.

> I get a compiler error if I remove it, saying there are multiple definitions of the pins in main.o.

Because by removing it, you're defining the variable in more than one translation unit, and thus assigning a different storage to the same variable name in different TUs.  There must be unambiguous storage for any given variable.