I have a global variable/buffer defined in a header. I have two source files, a function library (lib.c) and a test bench (tb.c), both include the header.
In the library, I fill the global variable buffer, print the pointer value and print some of the entries of the u8 buffer by iterating the pointer, i.e. [1, 2, 3, 4, 5 etc], with pointer 0xC8004C58 (buffer length = 2144).
Now in the test bench, I grab a pointer to this same global u8 buffer in exactly the same way. Now my interpretation is that the global variable remains in the same place so the pointer to its start should be the same, however instead I get pointer 0xC80054D8. Obviously as the pointer is now different, the returned data is [0, 0, 0, 0, 0 etc].
So:
If the the u8 buffer stays in the same place and is globally defined, why are my pointers to this buffer different depending on if I'm in lib.c or tb.c?
I'm creating my buffer in the header using:
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
I'm creating my pointer in the lib.c file using:
u32 *RxBufferPtr_Data = RxBuffer_Data;
I'm creating my pointer in the tb.c file using:L
u32 *RxBufferPtr_Data = RxBuffer_Data; or &RxBuffer_Data. Both of these return the same value, and neither are equal to the pointer that correctly prints out the data of the buffer in the lib.c file.
static instructs the compiler to instantiate a variable with internal linkage to the current translation unit (.c file plus all #included stuff). Internal linkage means the symbol (name) is not exported. Thus, the fact that you use matching names is irrelevant.
So, here, you get a separate instance for each .c file that #includes that header. Being separate objects, they of course have different addresses.
If you want to share a single instance (and hence address) among multiple TUs, then just do the usual:
Declare the variable as extern in a header - not static. Doing so indicates that it has external linkage, i.e. is defined elsewhere. Do not define the variable in the header. It must be defined only once, so...
Define the variable in a single .c file only.
Some light reading on the basics of static vs extern will make this all clear.
Each compilation unit contains its own buffer because you declared it as having internal linkage by providing keyword static in the buffer declaration in the header.
You should declare it in the header like
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
and in some module define it like
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
or just like
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
without the initializer because in any case it will be initialized with zeroes by the compiler as having static storage duration.
In this case the buffer will be shared by all compilation units that include the header.
Here is the problem:
I'm creating my buffer in the header using:
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
The above creates a separate copy of the variable in every c file from which the header is included. In other words, your would-be-globals from separate modules are invisible to the linker, which makes them unrelated to each other, and gives them separate addresses.
If you want to make a global variable, declare it in the header like this
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
then define it in the file containing your main() function like this:
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
You define RxBuffer_Data to staticin your head file,it tell compiler you just use this variable in this file.When lib.c include your head file,it define in lib.c.And RxBuffer_Data will re-define in tb.c when include head file,this RxBuffer_Data is a new variable.So,you can find two pointer to RxBuffer_Data is different.
If you want to define global varibal,you can define it in lib.c:
u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
and declare in your head file:
extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];
By the way,do not define global varibles in head file,because once you include this head file,you will re-define it.
Related
I am not very much familiar with modular structure of C programming, so I decided to ask you for help.
Let pretend I have two modules into the project. The one is sx1272.c and the other is sx1272_ll.c. The variable radio_is_on is declared in sx1272_ll.c as follows:
static uint8_t volatile radio_is_on;
and then accessed by function in sx1272.c like this:
foo(){
...............
if(radio_is_on){
blablabla...
............
}
...............
}
So if radio_is_on is static (in module scope) how come it is accessed by other modules?
sx1272_ll.c
sx1272.c
It seems to me that you included
#include "sx1272_ll.c"
in you your source file sx1272.c
So the whole content of file sx1272_ll.c is just copy-pasted into sx1272.c, at the position where you have written #include "sx1272_ll.c" during the pre-proccesing stage.
Refer this link: https://en.wikipedia.org/wiki/C_preprocessor#Including_files
you cannot declare variable static and access it from another module.
static has 3 usages:
1) if variable declared static whithin block (eg. function) it will maintial it's value during invocations.
int add(void){
static int var = 0;
var++;
return var;
}
int main(void){
printf("Var = %d", add()); // Here var = 1
printf("Var = %d", add()); // Here var = 2
return 0;
}
2) if variable declared static in a file, it can be accessed only within this file and no other file can access it.
If we declare
static uint8_t volatile radio_is_on; in file X, it will not be accessible in file Y.
3) if function declared static in a file, it can be accessed only within this file and no other file can access it.
The static keyword outside any function means, that variable (more strictly object represented by that variable) has internal linkage, which you can think as it is more or less private to that module, where it is defined. There would be no symbol generated in object file for such variable (you could inspect it with tools like nm or readelf).
You might either define it with external linkage by omitting static (optionally adding extern keyword), or if you need it to be static for some special reason (?), then write wrapper function, that exposes it into other module. It might be defined as:
sx1272_ll.c:
static uint8_t volatile radio_is_on;
uint8_t volatile *get_radio_is_on(void)
{
return &radio_is_on;
}
then put prototype into:
sx1272.c:
uint8_t volatile *get_radio_is_on(void);
There is no risk, that such pointer would point into invalid memory region, because file-scope variables have static storage duration, that means lifetime of whole application.
In the strictest sense its not possible to access static variables from other modules, that's exactly what the keyword is intended for.
But one way to do it is to add an external function is_radio_on() which returns its value.
I recently came across the question like how to access a variable which declared static in file1.c to another file2.c?
Is it possible to access static variable?
My understanding about static keyword in C is,
static is "internal linkage", so they are accessible only from one compilation unit - the one where they were defined. Objects declared with internal linkage are private to single module.
As one of my friend suggest me below solution.
In file1.c
#include <stdio.h>
int main()
{
int b=foo();
printf("%d",b);
return 0;
}
in file2.c
static int a=25;
int foo()
{
return a;
}
compiled by gcc file1.c file2.c -o file
If I do above I can access the variable.
So my questions are:
Does the above program violate static variable rules?
If not, why is this so, and is there any other way to access static variable except including file (#include <…>) not like this.
How am I able to access a static variable from another file?
In C, how do I restrict the scope of a global variable to the file in which it's declared?
Correct me if I'm wrong with static variable concept and if any better solutions are available to access static variable?
1) does the above program violate static variable rules?
No you are not vailoting any rules. Here foo function create copy of value of that static variable and used in other file. Its fine.
2) If not why is this so, and is there any other way to access static variable except including file (#include<>) not like this How am I able to access a static variable from another file?
Static variable are only mean to use in that file only.
You can not use that variable making them extern in other files.
Another dirty hack is to get pointer of that static variable and make that as global pointer and making that as extern in another file you can use that static variable.
file1.c
#include<stdio.h>
static int a=25;
int* ptr = &a;
file2.c
#include<stdio.h>
extern int *ptr;
int main()
{
printf("%d",*ptr);
return 0;
}
Correct me if I'm wrong with static variable concept and if any better solutions are available?
A static variable has a lifetime extends across the entire run of the program
If you do not initialize static variable with some value then its default value would be 0.
A static variable has scope limited to its file only. You can not access it by name from a different file.
You have temp1.c and temp2.c both are getting compiled together then also you can have static variable of same name in both files — and they are separate variables.
In C, how do I restrict the scope of a global variable to the file in which it's declared?
By making that global variable as static.
What we commonly call a variable in C is actually two things: an object, the memory allocated for the variable interpreted with a certain type, and an identifier, one way to access that object.
There is no problem in accessing a static object or its value from another compilation unit. Your function foo promotes the value to another unit, that is fine, but it could even promote the address of a without problems.
Having internal linkage only concerns the identifer, the name a. This one is only visible inside file2.c.
With the static int a=25; the variable a will have internal linkage; meaning the linker cannot see a anywhere outside of the file2.c TU.
When you're calling foo() in file2.c, you get a copy of a, it's the copy that you print; but this doesn't mean you have access to the actual a defined in file2.c When you need such an access where the same variable is visible across different TUs, you could do this
Defining file
This file both declares and defines the variable; additionally initializes it to 1 too, without which it'll be default initialized to 0.
// (non-static) global variable with external linkage and thus visible across TUs
int var_across = 0;
void use()
{
var_across = 1;
}
Using file
// just a declaration to tell that it's defined elsewhere; not a definition
extern int var_across;
void use_here()
{
var_across = 2;
}
Assigning address of static variable to pointer will make static variable available to subfiles.
In subfiles we have to use extern keyword to the pointer.
But it is not necessary to do that.
I have several 450 element character arrays (storing bitmap data to display on lcd screens.) I would like to put them under a header file and #define them, but I keep getting compilation errors. How would I do this in C?
#define numbers[450] {0, 1,etc...}
#define numbers {0, 1, etc...}
#define numbers[450] then set the numbers later
and many more...
Well... you certainly don't need to use a define. Just add them into the header as const, static arrays.
/* prevents multiple, redundant includes */
/* make sure to use a symbol that is fairly sure to be unique */
#ifndef TEST_H
#define TEST_H
/* your image data */
const char image[] = { 1, 2, 3, 4, ... };
#endif
Also, if you want help on a compilation error then you should post your code.
Because you are displaying on an LCD, I am assuming this is an embedded system.
Don't put the data into a header.
Put the data into an ordinary C or C++ file. Compile this. It might only contain the data, that is okay, and makes it easy to update.
Then use the header file to give access to the data.
For example, in a images.c file:
#include "images.h"
const byte numbers1[MAX_NUMBERS1] = { ... };
byte numbers2[MAX_NUMBERS2]; // will be initialsied to 0
Then images.h is:
#ifndef _IMAGES_H_
#define _IMAGES_H_
typedef unsigned char byte;
#define MAX_NUMBERS1 (450)
// different constants in case you change something
#define MAX_NUMBERS2 (450)
// even better if you can do const static int MAX_NUMBERS1=450;
// but depends on the compiler
extern const byte numbers1[MAX_NUMBERS1] = { ... };
extern byte numbers2[MAX_NUMBERS2]; // will be initialised to 0
#endif
Then all other .c files in the program can access them.
It is (almost) always a bad idea to put a definition of a variable into a header file.
A declaration of a variable, eg.
extern byte numbers2[MAX_NUMBERS2];
is telling the C compiler that there is an array variable called numbers2 somewhere else in the final, linked program. If the linker doesn't get that definition (from somewhere else) then it will raise an error because there is no space for the variable allocated.
A definition of a variable (notice no extern), eg.
byte numbers2[MAX_NUMBERS2];
is effectively telling the C compiler that there is an array variable called numbers2 and it should allocate the space here, in the resulting object code from this source file, and this will be used to hold the value of the variable in the final, linked program.
The space for numbers2 is not allocated by the C compiler when it sees a declaration (preceded by extern), it is allocated when it sees the actual definition (no extern).
So, if you put the actual definition of any variable in a header file, and include it into more than one source code files (.c), the C compiler will allocate space for the variable more than once. Then the linker will give an error (usually multiple definitions of the same name).
There is a more subtle problem. If, when first developing the program, the header file is only included is one source file, then the program will compile and link correctly. Then, at a later date, if a second source file includes the header (maybe someone has just split the original source code file into two files), the linker will raise a 'multiple definitions' error. This can be very confusing because the program used to compile and link, and apparently nothing has changed.
Summary
Never allocate space for a variable by putting a definition in a header file. Only put variable declarations in header files.
I have had a similar problem. In my case, I needed an array of constants in order to use as size of other static arrays. When I tried to use the
const int my_const_array[size] = {1, 2, 3, ... };
and then declare:
int my_static_array[my_const_array[0]];
I get an error from my compiler:
array bound is not an integer constant
So, finally I did the following (Maybe there are more elegant ways to do that):
#define element(n,d) ==(n) ? d :
#define my_const_array(i) (i) element(0,1) (i) element(1,2) (i) element(2,5) 0
What is the difference between static and extern in C?
From http://wiki.answers.com/Q/What_is_the_difference_between_static_and_extern:
The static storage class is used to declare an identifier that is a local variable either to a function or a file and that exists and retains its value after control passes from where it was declared. This storage class has a duration that is permanent. A variable declared of this class retains its value from one call of the function to the next. The scope is local. A variable is known only by the function it is declared within or if declared globally in a file, it is known or seen only by the functions within that file. This storage class guarantees that declaration of the variable also initializes the variable to zero or all bits off.
The extern storage class is used to declare a global variable that will be known to the functions in a file and capable of being known to all functions in a program. This storage class has a duration that is permanent. Any variable of this class retains its value until changed by another assignment. The scope is global. A variable can be known or seen by all functions within a program.
static means a variable will be globally known only in this file. extern means a global variable defined in another file will also be known in this file, and is also used for accessing functions defined in other files.
A local variable defined in a function can also be declared as static. This causes the same behaviour as if it was defined as a global variable, but is only visible inside the function. This means you get a local variable whose storage is permanent and thus retain its value between calls to that function.
I'm no C expert so I might be wrong about this, but that's how I've understood static and extern. Hopefully someone more knowledgable will be able to provide you with a better answer.
EDIT: Corrected answer according to comment provided by JeremyP.
You can apply static to both variables and functions. There are two answers that discuss the behaviour of static and extern with respect to variables, but neither really covers functions. This is an attempt to rectify that deficiency.
TL;DR
Use static functions whenever possible.
Only declare external functions in headers.
Use the headers where the functions are defined and where the functions are used.
Don't declare functions inside other functions.
Don't exploit the GCC extension with function definitions nested inside other functions.
External functions
By default, functions in C are visible outside the translation unit (TU — basically the C source file and included headers) in which they are defined. Such functions can be called by name from any code that notifies the compiler that the function exists — usually by a declaration in a header.
For example, the header <stdio.h> makes visible declarations of functions such as printf(), fprintf(), scanf(), fscanf(), fopen(), fclose(), and so on. If a source file includes the header, it can call the functions. When the program is linked, the correct library must be specified to satisfy the function definition. Fortunately, the C compiler automatically provides the library that provides (most of) the functions in the standard C library (and it usually provides a lot more functions than just those). The 'most of' caveat applies because on many systems (Linux, for instance, but not macOS), if you use functions declared in the <math.h> header, you need to link with the maths library ('math' library if you're American), which usually is indicated by the option -lm on the linker command line.
Note that external functions should be declared in headers. Each external function should be declared in one header, but one header may declare many functions. The header should be used both in the TU where each function is defined and in each TU that uses the function. You should never need to write a declaration for a global function in a source file (as opposed to a header file) — there should be a header to declare the function and you should use that header to declare it.
Static functions
As an alternative to generally visible functions, you can make your own functions static. This means that the function cannot be called by name from outside the TU in which it is defined. It is a hidden function.
The primary advantage of static functions is hiding details which the outside world doesn't need to know about. It is a basic but powerful information hiding technique. You also know that if a function is static, you do not need to look for uses of the function outside the current TU, which can greatly simplify the search. However, if the functions are static, there can be multiple TUs which each contain a definition of a function with the same name — each TU has its own function, which may or may not do the same thing as a function with the same name in a different TU.
In my code, I qualify all functions except main() with the keyword static by default — unless there's a header that declares the function. If I subsequently need to use the function from elsewhere, it can be added to the appropriate header and the keyword static removed from its definition.
Declaring functions inside other functions
It is possible, but very inadvisable, to declare a function inside the scope of another function. Such declarations fly in the face of Agile Development maxims such as SPOT (Single Point of Truth) and DRY (Don't Repeat Yourself). They're also a maintenance liability.
However, you can, if you so desire, write code such as:
extern int processor(int x);
int processor(int x)
{
extern int subprocess(int);
int sum = 0;
for (int i = 0; i < x; i++)
sum += subprocess((x + 3) % 7);
return sum;
}
extern int subprocess(int y);
int subprocess(int y)
{
return (y * 13) % 37;
}
The declaration in processor() suffices for it to use subprocess(), but is otherwise unsatisfactory. The extern declaration before the definition is necessary if you use GCC compiler options such as:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
> -c process.c
process.c:12:5: error: no previous prototype for ‘subprocess’ [-Werror=missing-prototypes]
int subprocess(int y)
^~~~~~~~~~
cc1: all warnings being treated as errors
$
This is, I find, a good discipline, similar to what C++ enforces. It's another reason I make most functions static, and define the functions before they're used. The alternative is to declare static functions at the top of the file and then define them in whatever order seems appropriate. There are some merits to both techniques; I prefer to avoid the need to declare and define the same function in the file by defining before use.
Note that you cannot declare a static function within another function, and if you attempt to define a function such as subprocess() as a static function, the compiler gives an error:
process.c:12:16: error: static declaration of ‘subprocess’ follows non-static declaration
static int subprocess(int y)
^~~~~~~~~~
process.c:5:20: note: previous declaration of ‘subprocess’ was here
extern int subprocess(int);
^~~~~~~~~~
Since functions that are externally visible should be declared in a header, there is no need to declare them inside a function, so you should never run into this as a problem.
Again, the extern is not necessary in the function declaration inside the function; if omitted, it is assumed. This can lead to unexpected behaviour in novice programs here on SO — you sometimes find a function declaration where a call was intended.
With GCC, the option -Wnested-externs identifies nested extern declarations.
Called by name vs called by pointer
If you have a nervous disposition, stop reading now. This gets hairy!
The 'called by name' comment means that if you have a declaration such as:
extern int function(void);
you can write in your code:
int i = function();
and the compiler and linker will sort things out so that the function is called and the result used. The extern in the declaration of the function is optional but explicit. I normally use it in a header file to match the declaration of those rare global variables — where the extern is not optional but mandatory. Many people disagree with me on this; do as you wish (or must).
Now what about static functions?
Suppose the TU reveal.c defines a function static void hidden_function(int) { … }.
Then, in another TU openness.c, you cannot write :
hidden_function(i);
Only the TU that defines the hidden function can use it directly. However, if there's a function in reveal.c that returns a function pointer to the hidden_function(), then the code openness.c can call that other function (by name) to get a pointer to the hidden function.
reveal1.h
extern void (*(revealer(void)))(int);
Obviously, that's a function that takes no arguments and returns a pointer to a function that takes an int argument and returns no value. No; it isn't pretty. One of the times it makes sense to use typedef on pointers is with pointers to functions (reveal2.h):
typedef void (*HiddenFunctionType)(int);
extern HiddenFunctionType revealer(void);
There: much simpler to understand.
See Is it a good idea to typedef pointers for a general discussion on the subject of typedef and pointers; the short summary is "it isn't a good idea except perhaps with function pointers".
reveal1.c
#include <stdio.h>
#include "reveal1.h"
static void hidden_function(int x)
{
printf("%s:%s(): %d\n", __FILE__, __func__, x);
}
extern void (*(revealer(void)))(int)
{
return hidden_function;
}
Yes, it is legitimate (but very unusual) to define the function with an explicit extern — I very, very seldom do it, but here it emphasizes the role of extern and contrasts it with static. The hidden_function() can be returned by revealer(), and could be called by code inside reveal.c. You can remove the extern without changing the meaning of the program.
openness1.c
#include <stdio.h>
#include "reveal1.h"
int main(void)
{
void (*revelation)(int) = revealer();
printf("%s:%s: %d\n", __FILE__, __func__, __LINE__);
(*revelation)(37);
return 0;
}
This file cannot usefully contain a direct call by name to hidden_function() because it is hidden in the other TU. However, the revealer() function declared in reveal.h can be called by name and it returns a pointer to the hidden function, which can then be used.
reveal2.c
#include <stdio.h>
#include "reveal2.h"
static void hidden_function(int x)
{
printf("%s:%s(): %d\n", __FILE__, __func__, x);
}
extern HiddenFunctionType revealer(void)
{
return hidden_function;
}
openness2.c
#include <stdio.h>
#include "reveal2.h"
int main(void)
{
HiddenFunctionType revelation = revealer();
printf("%s:%s: %d\n", __FILE__, __func__, __LINE__);
(*revelation)(37);
return 0;
}
Sample outputs
Not the most exciting output in the world!
$ openness1
openness1.c:main: 7
reveal1.c:hidden_function(): 37
$ openness2
openness2.c:main: 7
reveal2.c:hidden_function(): 37
$
Both of these modifiers have something to do with memory allocation and linking of your code. The C standard[3] refers to them as storage-class specifiers. Using those allows you to specify when to allocate memory for your object and/or how to link it with the rest of the code. Let’s have look on what exactly is there to specify first.
Linking in C
There are three types of linkage – external, internal and none. Each declared object in your program (i.e. variable or function) has some kind of linkage – usually specified by the circumstances of the declaration. Linkage of an object says how is the object propagated through the whole program. Linkage can be modified by both keywords extern and static .
External Linkage
Objects with external linkage can be seen (and accessed) through the whole program across the modules. Anything you declare at file (or global) scope has external linkage by default. All global variables and all functions have external linkage by default.
Internal Linkage
Variables and functions with internal linkage are accessible only from one compilation unit – the one they were defined in. Objects with internal linkage are private to a single module.
None Linkage
None linkage makes the objects completely private to the scope they were defined in. As the name suggests, no linking is done. This applies to all local variables and function parameters, that are only accessible from within the function body, nowhere else.
Storage duration
Another area affected by these keywords is storage duration, i.e. the lifetime of the object through the program run time. There are two types of storage duration in C – static and automatic.
Objects with static storage duration are initialized on program startup and remain available through the whole runtime. All objects with external and internal linkage have also static storage duration. Automatic storage duration is default for objects with no linkage. These objects are allocated upon entry to the block in which they were defined and removed when the execution of the block is ended. Storage duration can be modified by the keyword static .
Static
There are two different uses of this keyword in the C language. In the first case, static modifies linkage of a variable or function. The ANSI standard states:
If the declaration of an identifier for an object or a function has
file scope and contains the storage-class specifier static , the
identifier has internal linkage.
This means if you use the static keyword on a file level (i.e. not in a function), it will change the object’s linkage to internal, making it private only for the file or more precisely, compilation unit.
/* This is file scope */
int one; /* External linkage. */
static int two; /* Internal linkage. */
/* External linkage. */
int f_one()
{
return one;
}
/* Internal linkage. */
static void f_two()
{
two = 2;
}
int main(void)
{
int three = 0; /* No linkage. */
one = 1;
f_two();
three = f_one() + two;
return 0;
}
The variable and function() will have internal linkage and won’t be visible from any other module.
The other use of static keyword in C is to specify storage duration. The keyword can be used to change automatic storage duration to static. A static variable inside a function is allocated only once (at program startup) and therefore it keeps its value between invocations
#include <stdio.h>
void foo()
{
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main()
{
int i;
for (i = 0; i < 10; ++i)
foo();
}
The output will look like this:
a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60
Extern
The extern keyword denotes, that “this identifier is declared here, but is defined elsewhere”. In other words, you tell the compiler that some variable will be available, but its memory is allocated somewhere else. The thing is, where? Let’s have a look at the difference between declaration and definition of some object first. By declaring a variable, you say what type the variable is and what name it goes by later in your program. For instance you can do the following:
extern int i; /* Declaration. */
extern int i; /* Another declaration. */
The variable virtually doesn’t exist until you define it (i.e. allocate memory for it). The definition of a variable looks like this:
int i = 0; /* Definition. */
You can put as many declaration as you want into your program, but only one definition within one scope. Here is an example that comes from the C standard:
/* definition, external linkage */
int i1 = 1;
/* definition, internal linkage */
static int i2 = 2;
/* tentative definition, external linkage */
int i3;
/* valid tentative definition, refers to previous */
int i1;
/* valid tenative definition, refers to previous */
static int i2;
/* valid tentative definition, refers to previous */
int i3 = 3;
/* refers to previous, whose linkage is external */
extern int i1;
/* refers to previous, whose linkage is internal */
extern int i2;
/* refers to previous, whose linkage is external */
extern int i4;
int main(void) { return 0; }
This will compile without errors.
Summary
Remember that static – the storage-class specifier and static storage duration are two different things. Storage duration is a attribute of objects that in some cases can be modified by static , but the keyword has multiple uses.
Also the extern keyword and external linkage represent two different areas of interest. External linkage is an object attribute saying that it can be accessed from anywhere in the program. The keyword on the other hand denotes, that the object declared is not defined here, but someplace else.
Static
The static variables declared with the keyword static. The static variable initial value is 0. The static variables has block file scope scope.
Extern
A program in C, particularly when it is large, can be broken up into smaller programs. After compiling these, each program file can be joined together to form the large program. These small programs modules that combine together may need some variable that is used by all of them. In C, such a provision can be made by specifying these variables, accessible to all the small program modules, as an external storage class variable. These variables are global to all the small program modules that are formed as separate files. The keyword for declaring such global variables is extern.
Such a global variable is declared like any other variable in one of the program modules while the declaration of these variables is preceded with the keyword extern in all other combining program modules.
The program modules may also be a function or a block. These variables remain in existence as long as the program is in execution and their existence does not terminate upon the exit of a function or block or a program module from its state of execution. These variables are stored in the primary memory and their default value is zero.
Storage classes in C
Still confused with declaration and definition in term of C:
if a header file is like:
#ifndef _BASIC_H_
#define _BASIC_H_
void test();
extern int i; //define or declare
#endif
and two source file f1.c and f2.c contain this header, then one source file need to define the variable "i".
but if the header file is like:
#ifndef _BASIC_H_
#define _BASIC_H_
void test();
int i; //define or declare
#endif
and two source files f1.c and f2.c, contain this header without define the variable "i" in any file, it still goes through when I use the variable.
my questions is when the variable is defined.
Thanks
Defining a variable is when you allocate memory for the storage and maybe assign it a value. Declaring is when you state that a variable with a specific name and type exist, but memory has been allocated for it already.
The use of the extern keyword means that you are declaring the variable but not defining it.
In terms of your specific question, your first example is declaring and your second answer is defining.