I'm programming in C for firmware.
I have a header file: extern.h:
extern int x;
And I have file1.c:
#include"extern.h"
//----------foo1 gives value to x------------------------
foo1(void)
{
int x=200;
}
Now I have foo2 in file2.c
#include"extern.h"
foo2(void)
{
int x;
printf("%d",x);
}
And finally in main.c
#include"extern.h"
void main()
{
foo1();
foo2();
}
What could be the problem if get junk values in execution?
I trust the value of the variable must be 200.
I did a similar thing via mplab c18 and instead of printf in foo2.c, I did a transmission to the GUI function in foo2.c and it shows random int values in thousands and ten thousands..completely not related to the 200 that I gave.
And when i did initialize 'x' as
foo2(void)
{
int x;
}
It again shows random value in thousands.
I trust this not a problem with the coding i have done as it must transmit 200.
Note:
But on counter of that if initialize and transmit in foo2.c then the
values are displayed correctly.
Where should I look for bugs: in the GUI or in the Firmware?
When you say extern int x, it means that it is a global variable which is going to be defined in some other .c file. The local variables you have defined in foo1 and foo2 have precedence over the global extern variable. In foo1 the value of x will be 200 and in foo2 the value of x can be any value depending on what was there on the stack. Also I do not see where you have actually defined x to be a global variable. That is missing too.
foo1() -> does nothing
foo2() -> declares a variable x, which is UNDEFINED (no value has been set to it), so it could be anything.
Variables declared like int x; only have a lifetime of the scope they are in, i.e. you can't use the same name everywhere and expect it will map to the same variable.
If your variable is a global extern, don't redeclare it in the local foo functions you have.
See also
How do I use extern to share variables between source files?
When you place the line extern int x; in your extern.h file, what you're stating is that there exists an x somewhere but not here (well, not here unless you also have an int x; as well in the same scope).
In other words, it's a declaration that something exists rather than a definition that creates that something. So, without a definition, that particular x is never created.
In both your foo1() and foo2() functions, you do create something called x, however it's not the same x as the one you've declared in extern.h: it has different scope.
Both the x in foo1() and foo2() (and they are distinct variables, not the same one) are local to the function they're defined in. Hence foo1() creates its x, sets the value of it to 200 then throws that away on exit.
foo2(), on the other hand, creates its x with an arbitrary value and then prints it (hence your "junk value" comment).
That explains the behaviour you're seeing, now how to fix that. The way this is normally done is to define the variable somewhere (only once) and declare it wherever it's used, something like:
extern.h:
extern int x; // declare it
void foo1(void);
void foo2(void);
foo1.c:
#include "extern.h" // declare x via the header
void foo1(void) {
x = 200; // set x, note: no int at start of line
// since that would create a NEW x.
}
foo2.c:
#include <stdio.h>
#include "extern.h" // declare x via the header
void foo2(void) {
printf "%d\n", x); // again, no "int x;" since that would
// create a NEW x.
}
main.c:
#include "extern.h" // declare in the header
int x; // and define it.
int main (void) {
foo1();
foo2();
return 0;
}
So the "global" x exists in main.c (though you could put it in any of the C files, as long as it's only in one of them). The fact that both foo1.c and foo2.c include the extern.h header that declares the existence of x means that they'll be able to find it.
By ensuring that neither foo1() nor foo2() define another x in local scope (by using int x; or int x = something;), they'll use the x at the next outer scope (i.e, the one in main.c).
When you define an inner-scope variable of the same name as an outer scope one, the former "hides" (or "shadows") the latter. For example, the code:
#include <stdio.h>
int main (void) {
int x = 42;
printf ("A: %8d\n", x);
{
int x = 314159;
printf ("B: %8d\n", x);
}
printf ("C: %8d\n", x);
return 0;
}
will output:
A: 42
B: 314159
C: 42
as the inner braces create a new x within that scope. And, when the scope ends, the x you see then is the original one.
Related
In the program
case0.c
int main()
{
int x;
x = 4;
}
x is first declared as an int, and memory is allocated for x on the following line. No problems here.
However, if I write the files (as part of a bigger program)
case1.c
extern int x;
x = 4;
I get, from gcc, warning: data definition has no type or storage class. Similarly, if I do
case2.c
extern int x = 4;
gcc also doesn't like it and gives warning: 'x' initialized and declared 'extern'
The only case that doesn't throw any warnings is
case3.c
extern int x;
int x = 4;
Why does case 1 give an error, when case 0 doesn't? Is case 3 the one and only way I should define external variables?
x is first declared as an int, and memory is allocated for x on the following line. No problems here.
No, that is not what happens. Inside a function, int x; defines x, which reserves memory for it. Then x = 4; stores a value in that memory.
extern int x;
x = 4;
extern int x; declares there to be an x but does not define it. If the program uses this x, it should define it somewhere else.
Outside a function, only declarations should appear. However, x = 4; is a statement, so it is not proper outside a function.
extern int x = 4;
This is valid C, but it is unconventional usage, so the compiler warns you. Conventionally, we write int x = 4; to define and initialize x, and we write extern int x; to declare x without defining it.
extern int x = 4; is defined by the standard; in this context, it is effectively the same as int x = 4;. But programmers generally do not use that form.
(If there is a visible prior declaration of x, such as static int x;, then extern int x = 4; does differ from int x = 4;. extern int x = 4; will refer to the x of the prior declaration, whereas int x = 4; will attempt to create a new x.)
extern int x;
int x = 4;
extern int x; declares x but does not define it.
int x = 4; defines x and initializes it.
Is case 3 the one and only way I should define external variables?
If you only need to use x in one translation unit, you can use int x = 4; by itself, without extern int x;. If you need to use x in multiple translation units, you should put extern int x; in a header file and include that header file in each source file that uses x, including the one that defines it.
"Is case 3 the one and only way I should define external variables?"
No, not if it is to be visible and usable by other source files in the project. If it is only to be used in the file in which it is created, there is no reason to give it extern duration.
The scenario requiring a variable with extern duration is when the value it stores is required to be referenced by multiple source files.
A common way (place) to create extern variables to support that scenario :
Declare variable with extern modifier in a header file.
Define the extern variable in a project file with visibility to its declaration. (eg, can be either a .h or .c . More commonly done in .c) If defined in a file other than the declaration file, file must #include the declaration file.
Use the extern variable in any source file by # including its declaration file
Example:
file.h
//anywhere in header file
extern int g_number;//declare extern variable.
//Note extern keywork required only during declaration
//Not during definition
//prototypes
void output_extern_variable( void );
void update_extern_variable( void );
...
file.c
//in file global space
#include "file.h"
int g_number = 25;//define extern variable
int main(void)
{
output_extern_variable();
update_extern_variable();
output_extern_variable();
...
file2.c
#include "file.h"
...
void output_extern_variable(void)
{
printf("Value of g_number is: %d\n", g_number);
}
void update_extern_variable( int *var )
(
g_number += 1;
)
below is my code:
//main.c
int x = 9;
int f()
{
static int x = 0;
x += 1;
return x;
}
int main()
{
printf("Value is %d", f());
return 0;
}
my questions are:
Q1-inside f(), there is a local static varaible x defined, and there is gloabal variable also called x, the program does compile, but isn't it a conflict to the compiler and linker?
Q2-when I run it, the output is 1, which means that the x in x += 1; is the local static varaible x, not the gloabal variable x.But I could have mean "increment the global variable x", how can I do it?
A program can have the same name for local and global variables but the value of a local variable inside a function will take preference. There is no provision in C language to explicitly modify global variable with the same name as local inside local scope. In C++ though for accessing the global variable with same name, you'll have to use the scope resolution operator
#include <iostream>
using namespace std;
// Global variable declaration:
int g = 20;
int f()
{
int g = 0;
::g += 5;
return g;
}
int main () {
// Local variable declaration:
int g = 10;
cout << f(); // Local
cout << ::g; // Global
return 0;
}
Produces
0
25
Edit -
There is indeed a way to explicitly change the global scope variable inside local scope having same variable name ( only if global variable is not declared static )
int x = 9;
int f()
{
static int x = 0;
{
extern int x;
x += 1;
}
return x;
}
int main()
{
printf("Value is %d", f());
return 0;
}
Produces 0
Q1-inside f(), there is a local static varaible x defined, and there is gloabal variable also called x, isn't it a conflict to the compiler and linker?
No, the function always treats the local variable name first. The local name x in function f shadows the global name x.
Q2-when I run it, the output is 1, which means that the x in x += 1; is the local static varaible x, not the gloabal variable x.But I could have mean "increment the global variable x", how can I do it?
It's the same as your first question. You call f() which uses the local variable name x, which shadows the global name x. If you want the global x, you need to use it directly, not via function f.
Once conceptually, program control reaches the local declaration of x in f, the global x is shadowed. No syntax exists in C for accessing the global x.
Other than renaming one of the variables,
int f()
{
int* y = &x; // still refers to the global x
static int x = 0;
x += 1;
*y += 1; // increments the global x via the pointer
return x;
}
is an option, although not particularly sensible.
Q1. The language was intentionally designed this way so that we don't have to worry about what identifiers that reside in the global namespace - there can be quite a lot of them in large projects.
Internally the compiler doesn't use variable names at all, but sometimes their names must preserved for the purpose of generating debugger files (like ELF etc). In such situations, the compiler uses something called "name mangling" to keep the two variables separate internally. For example if I disassemble your code with gcc x86 and no optimizations, it names the local one x.0 internally, where the .0 thing is a compiler-specific addition, not to be confused with valid C syntax.
Q2. From inside the function f where the local x is visible, you can't. Unless you explicitly pass along a pointer to the other variable through a parameter etc. Again, we wouldn't want to change file scope variable values by accident.
Q1 -inside f(), there is a local static variable x defined, and there is global variable also called x, the program does compile, but isn't it a conflict to the compiler and linker?
No, it is not a conflict. What is going on here is the proce variable shadowing. The local x shadows the global x.
Q2 - when I run it, the output is 1, which means that the x in x += 1; is the local static variable x, not the global variable x. But I could have mean "increment the global variable x", how can I do it?
Declare the global variable new with extern inside an inner scope and return from that scope:
int f (void)
{
static int x = 0;
{
extern x;
x += 1;
return x;
}
}
Note that this won't work if the global x would be declared as static without adding code at the global space.
I am learning how to use a extern variable, I wrote a simple program to try it but it doesnt seem to be working. I've looked at some examples but I don't know whats wrong.
Here is my code:
globals.h
#ifndef GLOBALS_H_
#define GLOBALS_H_
extern int gval;
#endif /* GLOBALS_H_ */
main.c
#include <stdio.h>
#include "globals.h"
int main() {
int gval = 4;
printf("1st value is: %i", gval);
printf("2nd value is: %i", modded());
}
modify.c
#include "globals.h"
int modded() {
return gval++;
}
The error seems to be that gval is undefined in modify.c, but I don't get how.
As it stands, you've declared a global variable gval in the header, and you've hidden that global declaration with a locally defined variable gval in the main() function. This is legal, but only sometimes (I'm tempted to say 'occasionally' or 'seldom') what is intended. If you use GCC, using the -Wshadow option would warn you about shadowing variables like that. It is generally a bad idea to shadow global variables.
The simplest fix to your code is to move the definition of gval outside main():
#include <stdio.h>
#include "globals.h"
int gval = 4;
int main(void)
{
printf("1st value is: %i", gval);
printf("2nd value is: %i", modded());
return 0;
}
However, you should note that although it will compile and run, the second value printed will be the same as the first because modded() returns the unmodified version of the value. To see the effect, you need:
#include "globals.h"
int modded(void)
{
return ++gval;
}
Were it my code, there'd be a declaration of modded() in globals.h. You should not be calling a function without a prototype in scope according to C99 and C11 (the old and current C standard). Of necessity, the original C89 standard was more lax about that rule; it had to be to accommodate the pre-existing non-standard code. However, for code written in the 21st Century, there's no real excuse for not having a prototype in scope before you use a function.
A global extern variable must be defined somewhere, but in your code, the gval in main is a local variable, there's no definition of the global variable. This line
extern int gval;
is a declaration, not a definition. In other words, you must have
int gval;
somewhere outside all functions.
Even if a global gval were defined, note that the global gval is invisible in the scope of local gval
Change your main.c to
#include <stdio.h>
#include "globals.h"
int gval; // define (allocate space for) the global variable
int main(void) {
// int gval = 4; -- wrong -- this defines and initializes a local variable that hides the global of the same name
gval = 4; // use the global variable, assigning to it ... or you could initialize it at the definition above and omit this line
printf("1st value is: %i", gval);
printf("2nd value is: %i", modded());
}
and change modded to
int modded(void) {
// return gval++; -- wrong -- this is postfix increment and returns the value *before* incrementing
return ++gval; // use prefix increment
}
You also should have a modify.h that contains the prototype for modded that you include in main.c, or just put modded inside main.c before main.
Another approach is to change modded to not return a value, since it is changing a global, thus:
void modgval(void) {
++gval; // or gval++
}
And then in main:
printf("1st value is: %i", gval);
modgval();
printf("2nd value is: %i", gval);
Just put Gval before the main declaration and you're ready to go ;)
This is a simple example describing how to share a variable between source files:
File 1:
int GlobalVariable; // explicit definition, this actually allocates as well as describing
void SomeFunction(void); // function prototype (declaration), assumes defined elsewhere, normally from include file.
int main() {
GlobalVariable = 1;
SomeFunction();
return 0;
}
File 2:
extern int GlobalVariable; // implicit declaration, this only describes and assumes allocated elsewhere, normally from include
void SomeFunction(void) { // 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.
In your case gval in main is a local variable, instead define a global variable and then use extern to share variable in different source files.
I have this code:
#include <stdio.h>
extern int x;
void a() {
int x = 100;
printf("%d ",x );
x += 5;
}
void b() {
static int x = -10;
printf("%d ", x);
x += 5;
}
void c(){
printf("%d ", x);
x += 2;
}
int main() {
int x = 10;
a();
b();
c();
a();
b();
c();
printf("%d ", x);
getchar();
return 0;
}
int x = 0;
I was sure that the fact that extern in declared here, I will have a compilation error - but everything passed.
also , what is the meaning of extern when it's inside the C file itself? shouldn't it be in another file?
Is there a way to declare this variable in order for this not to compile?
The extern keyword declares a variable, and tells the compiler there is a definition for it elsewhere. In the case of the posted code, the definition of x occurs after main(). If you remove the int x = 0; after main() the code will not build (it will compile but will fail to link due to undefined symbol x).
extern is commonly used to declare variables (or functions) in header files and have the definition in a separate source (.c) file to make the same variable available to multiple translation units (and avoid multiple definition errors):
/* my.h */
#ifndef MY_HEADER
#define MY_HEADER
extern int x;
#endif
/* my.c */
#include "my.h"
int x = 0;
Note that the declaration of x in functions a(), b() and main() hide the global variable x.
You have a declaration for an identifier at file scope, so if no other declaration for the identifier would've been existing at file scope, the identifier would have had and external linkage. But, you've defined the identifier at file scope at the last line, in the pasted code.
So,extern int x;
refers to the globally defined: int x = 0; at the bottom of your file. :)
If you run this code you should get x's value as 2 and subsequently 4 because the externed x variable refers to the int x=0 after the main().
Extern is used for declaration a variable in a compilation unit, this variable was defined in other compilation unit.
What is the difference between a definition and a declaration?
For functions it is optional.
Read: http://en.wikipedia.org/wiki/External_variable
In your piece of code, each of the three function uses another 'i'. Only c() uses the global x.
Can anyone please tell me is there any special requirement to use either EXTERN or GLOBAL variables in a C program?
I do not see any difference in a program like below, if I change from gloabl to extern.
#include <stdio.h>
#include <stdlib.h>
int myGlobalvar = 10;
int main(int argc, char *argv[])
{
int myFunc(int);
int i;
i = 12;
myGlobalvar = 100;
printf("Value of myGlobalvar is %d , i = %d\n", myGlobalvar, i);
i = myFunc(10);
printf("Value of passed value : %d\n",i);
printf("again Value of myGlobalvar is %d , i = %d\n", myGlobalvar, i);
system("PAUSE");
return 0;
}
int myFunc(int i)
{
i = 20 + 1000;
//extern int myGlobalvar;
myGlobalvar = 20000;
// printf("Value of passed value : %d",i);
return i;
}
If uncomment extern int myGlobalvar, the value does not change.
Is there any correct difference between both?
Can anyone please correct me?
The keyword extern means "the storage for this variable is allocated elsewhere". It tells the compiler "I'm referencing myGlobalvar here, and you haven't seen it before, but that's OK; the linker will know what you are talking about." In your specific example it's not particularly useful, because the compiler does know about myGlobalvar -- it's defined earlier in the same translation unit (.c or .cc file.) You normally use extern when you want to refer to something that is not in the current translation unit, such as a variable that's defined in a library you will be linking to.
(Of course, normally that library would declare the extern variables for you, in a header file that you should include.)
From Here:
A global variable in C/C++ is a variable which can be accessed from any module in your program.
int myGlobalVariable;
This allocates storage for the data, and tells the compiler that you want to access that storage with the name 'myGlobalVariable'.
But what do you do if you want to access that variable from another module in the program? You can't use the same statement given above, because then you'll have 2 variables named 'myGlobalVariable', and that's not allowed. So, the solution is to let your other modules DECLARE the variable without DEFINING it:
extern int myGlobalVariable;
This tells the compiler "there's a variable defined in another module called myGlobalVariable, of type integer. I want you to accept my attempts to access it, but don't allocate storage for it because another module has already done that".
Since myGlobalvar has been defined before the function myFunc. Its declaration inside the function is redundant.
But if the definition was after the function, we must have the declaration.
int myFunc(int i)
{
i = 20 + 1000;
extern int myGlobalvar; // Declaration must now.
myGlobalvar = 20000;
printf("Value of passed value : %d",i);
return i;
}
int myGlobalvar = 10; // Def after the function.
In short: GLOBAL variables are declared in one file. But they can be accessed in another file only with the EXTERN word before (in this another file). In the same file, no need of EXTERN.
for example:
my_file.cpp
int global_var = 3;
int main(){
}
You can access the global variable in the same file. No need to use EXTERN:
my_file.cpp
int global_var = 3;
int main(){
++global_var;
std::cout << global_var; // Displays '4'
}
Global variable, by definition, can also be accessed by all the other files.
BUT, in this case, you need to access the global variable using EXTERN.
So, with my_file.cpp declaring the global_var, in other_file.cpp if you try this:
other_file.cpp
int main(){
++global_var; // ERROR!!! Compiler is complaining of a 'non-declared' variable
std::cout << global_var;
}
Instead, do:
int main(){
extern int global_var;//Note: 'int global_var' without 'extern' would
// simply create a separate different variable
++global_var; // and '++global_var' wouldn't work since it'll
// complain that the variable was not initiazed.
std::cout << global_var; // WORKING: it shows '4'
}
myGlobalVar as you've defined it is a global variable, visible from all the places in your program. There's no need declaring it extern in the same .c file . That is useful for other .c files to let the compiler know this variable is going to be used.