my first question here.
can anyone explain to me the differnce between a global static variable (that is, defined above the functions and the "main" combined with "static") and a static variable that is defined inside a function?
as i understand it, they do the same - both enlarge the variable scope to the whole file, and both restrict it to the specific file. so... what am i missing?
plus another question (that came up when looking for a solution) - what is extern? i thought that defining a variable above the main would make it global (as in to other files too), but then i read someone explaining that in order to do so, i must add "extern" before the varible defining.
For variables defined outside of a function, the static keyword limits the variable to being referenced using its identifier from the file in which it is defined. Variables of this type will be assigned a fixed address by the linker (outside of the heap and stack), but will not be assigned a global symbol. If variables of this type are defined in multiple files with the same identifier, the linker should allocate separate memory in each case and should compile without warnings.
Variables defined with the static keyword inside of a function have similar memory allocation, but references to the variable using its identifier are limited to within that function. You could have multiple functions defining static variables with the same identifier and each will be allocated separately.
If an initializer is used for static variables, the variable is initialized once before the program begins executed and the initializer is evaluated at compile time. The initializer must evaluate to a constant expression in this case (no function calls or parameter or variable references).
The compiler will typically build each C file independent of all of the others in a program using symbols to define external dependencies, such as variables and functions located in other files. After each source file is compiled, the linker processes the compiler output to replace symbols with fixed addresses and build the entire program. In order to properly execute the build, the compiler must know the types and sizes of all external functions and variables. The type and number of parameters and return type of functions are typically shared in a header file using function prototype declarations. Function prototype declarations are implicitly identified as external by the compiler. The extern keyword is used to specify the type and size of variables declared in files outside of the file referencing the variable. Declaring a variable without the external keyword would cause it to be defined within the module where it is declared. If two variables with the same identifier are declared in multiple files without the static keyword, then the compiler will typically generate an error since the same global symbol is used multiple times in the program.
Related
I have read a lot about extern variables but no one seems to address it appropriately. If I declare and define a variable in C, it gets memory assigned in that scope of the file. but at a later stage in multi-file modular project that variable is declared as an extern which should store the it in the Data segment to exhibit the global behavior intended with the extern functionality.
So I am trying to figure out how and when the memory is being allocated, i.e. the compile time and run time behavior of the extern variable.
One of the compilation units has to define the variable as a global variable. When compiling this file, memory is allocated for the variable in the data segment, similar to file scope variables. The difference is that the variable is registered in the linkage table so that other object files can find it.
All the other compilation units declare it using the extern keyword. This prevents them from allocating memory for the variable, and arranges for the linker to find the external variable.
When you link all the object files together, the linker finds all the object files that have the external reference to the variable, and connects that link to the memory that was allocated in the first object file.
#include<stdio.h>
static int a=5;
main()
{
static int a=15;
printf("%d\n",a);
}
So, how are both variables a stored in internal memory?
How are global and local variables with the same variable names stored internally in memory?
#include<stdio.h>
static int a=5;
int main()
{
printf("%p\n",(void *)&a);
static int a=15;
printf("%p\n",(void *)&a);
return 0;
}
Output for the upper program is
0x564e6b67a030
0x564e6b67a034
So you can see that both are stored in different addresses. As one is a global variable and other is local.
The names are only of interest to the human reader and the compiler/linker translating that code to machine executable code. The final object code resolves these to addresses and the names no longer exist.
The compiler distinguishes these the same way you do - by scope; when two identical symbols in the same namespace are in scope simultaneously, the symbol with the most restrictive scope is visible (i.e. may be accessed via the name).
For symbols with external linkage (in your example there are none other then main), the compiler retains the symbol name in order to resolve links between separately compiled modules. In the fully linked executable the symbol names cease to exist (except in debug build symbol meta-data).
The thing is the scope don't let them mess up. The first one has file scope and the other has block scope. (They are different variables - they are stored in separate memories.)
When you use it in the block - compiler checks whether this reference is resolved by anything in the same block. It gets one. And done.
And in case it is in some other function - if it doesn't find anything named a - the search ends in file scope where it finds the name a. That is where the story ends.
Both being static their storage duration is same. They live till the program exists. But their scope is different. If the scope was same too - compiler would have shown you error message.
Here if you compile with -Wshadow option - it will warn you about shadowing a variable. You shadowed the outer a with the inner on that block. That's it.
The facetious answer is that they are stored in different places.
Remember that the names of variables do not (normally) form part of the compiled program, so the compiler just follows the normal rules of variable shadowing. So in your case your print function (that's not a standard C function by the way - did you mean printf?) outputs the a declared in main. The fact that you've used the same name will not bother the compiler at all.
Finally C provides no way of accessing the global scoped a once the other declaration is encountered in main as it's static. (It is wasn't static you could use extern.) See How can I access a shadowed global variable in C?
Can anyone please tell me that why the functions parameters can not be static?
Is this the reason that function parameters are declared on Stack and gets de-allocated when function return? There is no way to retain parameter values? Just confused. Please clarify.
Thanks.
The keyword static can probably be seen as somewhat "overloaded".
The following usage-options are all viable:
Static local variables
Static global variables
Static member variables
Static global functions
Static member functions
Variables:
In terms of runtime, all types of static variables are essentially the same. They all reside in the data-section of the program, and their addresses remain constant throughout the execution of the program. So the only difference between them is during compilation, in the scope of declaration:
Static local variable: recognized by the compiler only in the scope of the function
Static global variable: recognized by the compiler only in the scope of the file
Static member variable: recognized by the compiler only in the scope of the class
Functions:
In terms of runtime, all types of functions (static and non-static) are essentially the same. They all reside in the code-section of the program, and their addresses remain constant throughout the execution of the program. So the only difference between them is during compilation, in the scope of declaration:
Static global function: recognized by the compiler only in the scope of the file
Static member function: recognized by the compiler only in the scope of the class
As to your question, arguments are passed to a function in the stack. There is no sense in having them static, because that would effectively place them in the data-section. And if they are located in the data-section, then the function can simply read them from there instead of having them passed to it in the stack.
I understand that a static function in C allows that particular function to only be call within the confines of that file. What I am interested in is how this occurs. Is it being placed into a specific part of memory or is the compiler applying a specific operation to that function. Can this same process be applied to a function call in assembly?
Declaring a function static doesn't really prevent it from being called from other translation units.
What static does is it prevents the function from being referred (linked) from other translation units by name. That will eliminate the possibility of direct calls to that function, i.e calls "by name". To achieve that, the compiler simply excludes the function name from the table of external names exported from the translation unit. Other than that, there's absolutely nothing special about static functions.
You still can call that function from other translation units by other means. For example, if you somehow obtained a pointer to static function in other translation unit, you can call it through that pointer.
It doesn't make it into the object's name table which prevents it from being linked into other stuff.
Functions and other names are exported as symbols in the object file. The linker uses these symbols to resolve all sorts of dangling references at link time (e.g. a call to a function defined in another file). When you declare it static, simply it won't be exported as a symbol. Therefore it won't be picked up by any other file. You could still call it from another file if you had a function pointer to it.
It's in fact the opposite. When a function is not static, its name is written somewhere in the object file, which the linker can then use to link other object files using this function, to the address of that function.
When the function is declared static, the compiler simply doesn't put the name there.
I am new to Linux. I came across this piece of code to print environmental variables. It is kind of confusing me. How can this code print the environmental variables?
#include <stdio.h>
extern char **environ;
int main()
{
char **var;
for(var=environ; *var!=NULL;++var)
printf("%s\n",*var);
return 0;
}
what is extern here?
If you don't know what extern means, please find a book to learn C from. It simply means 'defined somewhere else, but used here'.
The environ global variable is unique amongst POSIX global variables in that it is not declared in any header. It is like the argv array to the program, an array of character pointers each of which points at an environment variable in the name=value format. The list is terminated by a null pointer, just like argv is. There is no count for the environment, though.
for (var = environ; *var != NULL; ++var)
printf("%s\n", *var);
So, on the first iteration, var points at the first environment variable; then it is incremented to the next, until the value *var (a char *) is NULL, indicating the end of the list.
That loop could also be written as:
char **var = environ;
while (*var != 0)
puts(*var++);
From wikipedia http://en.wikipedia.org/wiki/External_variable:
Definition, declaration and the extern keyword
To understand how external variables relate to the extern keyword, it is necessary to know the difference between defining and declaring a variable. When a variable is defined, the compiler allocates memory for that variable and possibly also initializes its contents to some value. When a variable is declared, the compiler requires that the variable be defined elsewhere. The declaration informs the compiler that a variable by that name and type exists, but the compiler need not allocate memory for it since it is allocated elsewhere.
The extern keyword means "declare without defining". In other words, it is a way to explicitly declare a variable, or to force a declaration without a definition. It is also possible to explicitly define a variable, i.e. to force a definition. It is done by assigning an initialization value to a variable. If neither the extern keyword nor an initialization value are present, the statement can be either a declaration or a definition. It is up to the compiler to analyse the modules of the program and decide.
A variable must be defined once in one of the modules of the program. If there is no definition or more than one, an error is produced, possibly in the linking stage. A variable may be declared many times, as long as the declarations are consistent with each other and with the definition (something which header files facilitate greatly). It may be declared in many modules, including the module where it was defined, and even many times in the same module. But it is usually pointless to declare it more than once in a module.
An external variable may also be declared inside a function. In this case the extern keyword must be used, otherwise the compiler will consider it a definition of a local variable, which has a different scope, lifetime and initial value. This declaration will only be visible inside the function instead of throughout the function's module.
The extern keyword applied to a function prototype does absolutely nothing (the extern keyword applied to a function definition is, of course, non-sensical). A function prototype is always a declaration and never a definition. Also, in ANSI C, a function is always external, but some compiler extensions and newer C standards allow a function to be defined inside a function.
An external variable must be defined, exactly once, outside of any
function; this sets aside storage for it. The variable must also be
declared in each function that wants to access it; this states the
type of the variable. The declaration may be an explicit extern
statement or may be implicit from context. ... You should note that we
are using the words definition and declaration carefully when we refer
to external variables in this section. Definition refers to the place
where the variable is created or assigned storage; declaration refers
to places where the nature of the variable is stated but no storage is
allocated.
—The C Programming Language
Scope, lifetime and the static keyword
An external variable can be accessed by all the functions in all the modules of a program. It is a global variable. For a function to be able to use the variable, a declaration or the definition of the external variable must lie before the function definition in the source code. Or there must be a declaration of the variable, with the keyword extern, inside the function.
The static keyword (static and extern are mutually exclusive), applied to the definition of an external variable, changes this a bit: the variable can only be accessed by the functions in the same module where it was defined. But it is possible for a function in the same module to pass a reference (pointer) of the variable to another function in another module. In this case, even though the function is in another module, it can read and modify the contents of the variable—it just cannot refer to it by name.
It is also possible to use the static keyword on the definition of a local variable. Without the static keyword, the variable is automatically allocated when the function is called and released when the function exits (thus the name "automatic variable"). Its value is not retained between function calls. With the static keyword, the variable is allocated when the program starts and released when the program ends. Its value is not lost between function calls. The variable is still local, since it can only be accessed by name inside the function that defined it. But a reference (pointer) to it can be passed to another function, allowing it to read and modify the contents of the variable (again without referring to it by name).
External variables are allocated and initialized when the program starts, and the memory is only released when the program ends. Their lifetime is the same as the program's.
If the initialization is not done explicitly, external (static or not) and local static variables are initialized to zero. Local automatic variables are uninitialized, i.e. contain "trash" values.
The static keyword applied to a function definition prevents the function from being called by name from outside its module (it remains possible to pass a function pointer out of the module and use that to invoke the function).
Example (C programming language)
File 1:
int GlobalVariable; // implicit definition
void SomeFunction(); // function prototype (declaration)
int main() {
GlobalVariable = 1;
SomeFunction();
return 0;
}
File 2:
extern int GlobalVariable; // explicit declaration
void SomeFunction() { // function header (definition)
++GlobalVariable;
}
In this example, the variable GlobalVariable is defined in File 1. In order to utilize the same variable in File 2, it must be declared. Regardless of the number of files, a global variable is only defined once, however, it must be declared in any file outside of the one containing the definition.
If the program is in several source files, and a variable is defined in file1 and used in file2 and file3, then extern declarations are needed in file2 and file3 to connect the occurrences of the variable. The usual practice is to collect extern declarations of variables and functions in a separate file, historically called a header, that is included by #include at the front of each source file. The suffix .h is conventional for header names.
Extern defines a variable or a function that can be used from other files... I highly advise reading some of the many articles available on the Internet on C programming: https://www.google.ca/search?client=opera&rls=en&q=learn+c&sourceid=opera&ie=utf-8&oe=utf-8&channel=suggest
extern char **environ;
the variable environ comes from your library which you will link.
That variable saved the system environment variables of your current
linux system. That's why you can do so.