I am facing following quirky error.
I have a workspace in MSVS2005 of all C code. I have declared a global variable in one C file.(file1.c) This file has function main() in which, I initilaize the value of that variable = 0.In other C file(file2.c). From main there is a function call to a function(func1 in file2.c) which sets the value of this global variable to 1. In file2.c I have declared the global variable as "extern .." and accessed it. But what i noticed is that in the main function moment the code execution enter the function func2, I see in the watch window that the address of that global variable itself is changed to a totally different address(In watch window I am watching &variable). As a result, when the value of that variable is set to 1, it writes the value 1 to altogether different memory address itself. So when later I use this variable to check in a if condition(if variable == 1), it still shows value of 0 and does not go satisfy the if condition and does not take that code path , where it was expected to have taken that path.
Workaround:
I declared that variable in one of my exisitng global structure, and then accessed this variable for doing the same operations; the code works as expected.
So what could be the explanation for the error which is causing the address of the global variable to be changed if its declared as a global in some C file? It does not matter in which *.c file i declare it and which file I access it using "extern" , the result is same global variable address change and subsequent errorneous operation.No optimization option is enabled.
Thanks,
-AD
Can only guess without actually seeing the code, but here are 2 possibilities:
the global variable is being hidden by a local in either main() or func2() (or maybe func1() - the question mentions func1() but I suspect that's a typo - this is why cutting and pasting code is quite important);
you are mistakenly declaring the global variable as static in file1.c and have an initializer on your extern declaration in file2.c. Having an initializer on the extern declaration will cause that declaration to be a definition, too.
Maybe try declaring it volatile (not sure if that's even valid for globals) and disable any compiler optimizations in case it's getting tricky somehow.
If the variable has a different address in different translation units, you are not seeing one but at least two variables with the same name.
Most common cause: You may have accidently declared a local variable on the stack with the same name. Check your code for this. If the variables are really global the linker should complain if two translation units contain the same symbol.
If this does not help, and if you still see multiple copies of the same symbol-name it's probably best to take a look at the map file (can be enabled in the linker-settings).
All external symbols are listed there with their name, address and (most important in your case) the object-file that contained them.
The addresses in the map-file may be just offsets. In this case do all your calculations relative to a symbol that is known to exist only once. the main() entrypoint might be good for this.
Probably a typo or some thing similar in your code. Try this working demo:
file1.c
int variable;
void fun1(int k);
int main()
{
printf("%d\n", variable);
fun1(4);
printf("%d\n", variable);
}
file2.c
extern int variable;
void fun1(int k)
{
variable = k;
}
Output:
0
4
To compile:
cl.exe file1.c file2.c
Related
The question is not "why can't I initialize a variable declared as extern", because it's something completely possible with file scope variables (not with block scope variables). The thing is that GCC yields a warning (with -Wall switch) in this particular case:
extern int n = 10; // file scope declaration
GCC yields:
test.c:5:12: warning: ‘n’ initialized and declared ‘extern’
The code works perfectly, though.
Furthermore, note that the following definition is absolutely equivalent to the first one:
int n = 10; // file scope declaration
In both cases, the variable has the same linkage and storage type. The thing is that, being both absolutely equivalent, the second version doesn't yield any warning in GCC (with -Wall).
Why is that?
My guess is that you usually use extern to explicitly set a reminder about the fact that this is a declaration that refers to an external object defined elsewhere, so that you shouldn't (though you could) initialize the variable (bear in mind that the standard doesn't let you define a variable twice inside the same linkage, in this case, external).
So, is that a right guess, or perhaps there's more to it, which I'm not able to see?
A compiler can warn about anything it likes to. If it is attentive, it warns about things it considers as "suspicious".
So it does here.
My personal opinion about the reasoning agrees to yours:
My guess is that you usually use extern to explicitly set a reminder about the fact that this is a declaration that refers to an external object defined elsewhere so that you shouldn't (though you could) initialize the variable (bear in mind that the standard doesn't let you define a variable twice inside the same linkage, in this case, external).
That GCC finds it suspicious to initialize an explicit extern declared variable because it is usually more common to define the variable in one file and then in another file, which can depend on the context, cause an error at linking and indeed can be the reason but our assumptions aren't worth much.
The question for the actual "why" you need to ask the implementors of GCC itself.
The keyword extern is used to declare a variable but not define it (similar to function declarations). It is typically used in header files to export a variable from a module. However, it is often better to introduce a function which returns its value.
Example:
M.h
extern int M_n;
M.c
int M_n = 10;
#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?
For our assignment we have to code a program in C, but it says not to use external variables in the program. Does this mean variables in other files brought into the main code, or am I unable to use variables in the same file if they're not in the same function? (ie: could I pass a value into a function as an argument and have it return a value that may have to do with a variable in that function and set the return value equal to something, or is that using external variables?)
I've Googled around but it's not exactly clear, and I want to make sure, as this is rather important.
Just to be sure, I'd make all my variables part of a function, and either pass them as parameters or return them from the functions.
There are at least two interpretations of external variables.
First off, we have the extern keyword, which basically symbolizes what you would call a global variable. It's a variable declared in multiple translation unit, but it only exists in one place in memory. It is initialized in a single file and all subsequent changes affect every scope the variable is used in:
//globals.cpp
int x = 1337;
//main.cpp
extern int x;
int main()
{
//x is 1337 here
return 0;
}
The second meaning could be a variable that is declared and defined in class scope, but not used as extern. However, you could consider it external to the methods.
//main.cpp
int x = 1337; //is this external?
//could be, remove it just to be safe
int main()
{
return 0;
}
Let's go with all the possible cases, because from your question I'm not too sure either:
There is extern as a keyword. In order to understand this, you need to understand compilation units. Basically, each file is a compilation unit - so each .c is compiled to a .o with the headers substituted in place. In each compilation unit, you forward declare symbols you expect to use - functions belonging to other compilation units, for example.
Now, if you declare a global variable in one .c file, it is global wrt that file, but does not exist as a symbol in any other file at all - the compiler will error because it doesn't know where that variable was declared.
(Of course, if you declare the variable in a header - it will exist in all of the objects the header is included in, and then the linker will sulk, because when it links all the objects up some of the symbols will have the same name).
To get around this, it is possible to define a variable with extern int x;, for example. This tells the compiler a) int x should be available to this compilation unit, b) int x is not in this compilation unit and c) the linker should check it exists somewhere in all the units you've put together to form a library or program.
Conceptually, you're doing this all the time with forward-declarations of functions. There's just no way to forward declare a variable. In fact, you can do this with functions too and not bother r.e shared headers, although this is not really a good idea.
The other case is that "external variables" mean something external to a certain scope or module you have. I would check your assignment very carefully and if in doubt ask - whoever set it should be able to explain to you exactly what they mean.
An external variable is a variable with external linkage.
A variable with external linkage is a variable defined at file scope without the static keyword.
int bla = 0; // external variable
static int blop = 1; // non-external variable
int main(void)
{
return bla
}
Note that a variable declared with the extern keyword doesn't necessarily have external linkage. Like const does not mean constant in C, extern does not mean external.
People often use the word external to say that a variable is actually declared in the current translation unit but is defined in another translation unit.
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.
include
static int i = 10;
int
main()
{
static int i = 20;
printf ( "i = %d\n", i );
return 0;
}
There are two static variables, one in global scope and one in function scope. The compiler is not throwing "multiple definition" error.
Could you please let me know where the two static vars are stored?
The two variables are stored separately because they are distinct - it is the compiler's problem to ensure that they are separate.
The variables are both initialized before the program starts - this is C, not C++, where the rules are slightly different.
Inside main() as shown, you cannot access the global variable i (again, this is C, not C++).
GCC's -Wshadow compiler flag would warn you about the local i shadowing the global one.
These variables are called "symbols", and during compiling a table is generated, the "symbol table". This table contains the name, type, scope and memory pointer to each symbol (this is like the minimum, you usually have a bunch of more stuff), and each time a reference is made to an symbol in a specific scope, it's substituted for an index into the table. These indices are unique, so is the combination of name+scope.
So in short, the names of the variables are simply decoration, internally the compiler works with a symbol table and indices into it. Statics are initialized during program startup by iterating through a table of pointers to them and putting the correct values in place.