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.
Related
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.
I have some doubt on below code
#include<stdio.h>
int i=6;
int main()
{
int i=4;
{
extern int i;
printf("%d",i); //prints 6
}
printf("%d",i); //prints 4
}
we know that extern keyword says compiler, the variable is somewhere outside. So the question is why the extern keyword is accessing the global i variable but not the i variable which is within the main function? I was thinking there must be a contradiction because both variables are available to the inner braces as global variable. So does extern keyword access the variable which is outside the function or does it also access the variable which is outside the braces.
extern doesn't mean outside the current scope, it means an object with external linkage. An automatic variable never has external linkage, so your declaration extern int i can't possibly refer to that. Hence it's hiding it, the same as the automatic variable hid the global.
Before the printf that prints 6 you are asking the compiler to use the i defined after the #include. The closing brace then tells the compiler that the extern is no longer in effect, therefore it uses the scope where i is set to 4.
int i=4 is not global variable, if you try to access var i which is inside main in another function your compiler will thrown error about var i is undeclared. This code illustrates it.
void func() {
printf("i is %d\n",i);
}
main() {
int i=10;
func();
}
Whereas the i outside of main is global variable, which you can access in all functions.
I think you're asking whether you're right in thinking that the extern int i declaration should cause the first printf to resolve i to 4 because that int i=4 statement is in a parent scope of the scope in which the extern is declared.
The answer is no, hence the behaviour you're seeing. An extern declaration within a function is used to declare the existence of an external variable and won't ever resolve to a local variable (a variable declared within the function).
/* what Ed Heal said */
Yet, I think it would be best to illustrate it with additional example. I modified Your example to do a little more. The comments in the code tells the most of it:
#include <stdio.h>
int i = 6;
int main(void)
{
int i = 4;
printf("%d\n", i); /* prints 4 */
{
extern int i; /* this i is now "current". */
printf("%d\n", i); /* prints 6 */
{
int *x = &i; /* Save the address of the "old" i,
* before making a new one. */
int i = 32; /* one more i. Becomes the "current" i.*/
printf("%d\n", i); /* prints 32 */
printf("%d\n", *x); /* prints 6 - "old" i through a pointer.*/
}
/* The "previous" i goes out of scope.
* That extern one is "current" again. */
printf("%d\n", i); /* prints 6 again */
}
/* That extern i goes out of scope.
* The only remaining i is now "current". */
printf("%d\n", i); /* prints 4 again */
return 0;
}
I need to include some typedef definition in two source files:
typedef double mat[MATSIZE][MATSIZE] ;
so I created def.h which includes:
#ifndef DEF_H
#define DEF_H
typedef double mat[MATSIZE][MATSIZE] ;
#endif
and in both .c files I included it by:
in the first file processed:
#define MATSIZE 4
#include "def.h"
in the second .c file:
extern int MATSIZE;
#include "def.h"
But I get
error: variably modified ‘mat’ at file scope
What did I do wrong?
The concept of Variable Length Arrays (VLAs) is "new" to C99.
Before C99 you could only use real constants for specifying sizes of arrays. The following code was illegal either in block scope or file scope.
const int size = 42; /* size is not a real constant */
int boo[size];
C99 introduced VLA for block scope. The example code above is legal C99, provided it happens in block scope. Your definition is at file scope and therefore invalid.
Also it is a really bad bad idea to have the same typedef refer to two different types.
When arrays are defined outside a block (at file scope or global scope), the size must be known at compile time. That means that the each dimension on the array must be a constant integral value (or, for the first dimension, it could be implied by the initializer for the array).
If you used a C89 compiler, you might get a message about non-constant array dimensions. GCC 4.6.1 gives the 'variably modified mat at file scope' message.
C99 added Variable Length Arrays to the repertoire, but they can only appear inside a block or an argument list, where the size can be determined at runtime.
So, in a function, you could legitimately write:
extern int MATSIZE;
extern void func(void);
void func(void)
{
typedef double mat[MATSIZE][MATSIZE];
// ...
}
(The function declaration is needed to avoid the warnings like:
warning: no previous prototype for ‘func’ [-Wmissing-prototypes]
since I habitually compile with -Wmissing-prototypes.)
The other issue is that in one file, MATSIZE is a compile-time (#defined) constant; in the other, there is apparently an integer variable MATSIZE. These are completely unrelated. The types therefore are different.
typdef is block scoped
wildplasser is concerned about whether typedef is block-scoped or global. It is block-scoped, as this otherwise execrable code demonstrates:
#include <stdio.h>
static void function(void)
{
typedef int i;
i j = 1;
printf("j = %d\n", j);
{
typedef double i;
i j = 2.1;
printf("j = %f\n", j);
}
{
typedef char i[12];
i j = "this works";
printf("j = %s\n", j);
}
}
int main(void)
{
function();
return(0);
}
If that was present to me for code review, it would be summarily rejected. However, it amply demonstrates a point.
MATSIZE is not known. Which is why you are getting this issue.
#ifndef DEF_H
#define DEF_H
#define MATSIZE 100 /* or whatever */
typedef double mat[MATSIZE][MATSIZE]
#endif
int main()
{
extern int i;
i=20;
printf("%d",i);
return 0;
}
The compiler is giving an Error that 'i' is undefined
Whats the Reason?
Difference :
1.int i; // i is defined to be an integer type in the current function/file
2.extern int i; // i is defined in some other file and only a proto-type is present here.
Hence while compiling, the compiler(LDD) will look for the original definition of the variable and if it does'nt find, it'll throw an error 'undefined reference to `i'.
By saying extern you tell the compiler that i is defined in a different translation unit, which I'm guessing you don't have. There's a difference between declaration and definition in C. In short, the former is telling the compiler the type of the variable, the latter is telling to allocate storage for it.
Just drop that extern for now.
i has no storage location.
You must link with a translation unit that includes int i; (not extern).
extern
Allows one module of your program to access a global variable or function declared in another module of your program.
You usually have extern variables declared in header files.
If you don't want a program to access your variables or functions, you use static which tells the compiler that this variable or function cannot be used outside of this module.
errno.h
#ifndef ERRORS /* prevent multiple inclusion */
#define ERRORS 0
extern int errno; <- Declaring the variable to be external.
extern void seterrorcode(int errcode);
#endif
errno.c
#include "errno.h"
int errno; <- This is where the definition of errno occurs
static int stuff; <- This is private to this module.
void seterrorcode(int errcode)
{
errno = errcode;
}
main.c
#include "errno.h"
/* extern int stuff : This line will produce an undefined variable error when linking */
int main()
{
seterrorcode(0);
if (errno > 0)
; /* Error code > 0, do something */
}
For more Info
extern keyword is used to tell the compiler that the variable
is defined in another file
but during linking, the linker does not resolve the variable
so you get an error
1.For this question,you need to understand that definition is a superset of declaration.In declaration,we just introduce the variable that is going to be used but do not allocate any memory to it.But in the case of definition,we both declare and allocate memory to the variable.
2.int i;
This sentence will both declare and define the variable i
3.On the other hand
extern int i;
This sentence will just extend the visibility of the variable to the whole program.Effectively,you are just defining the variable and not declaring it.
i=20;
this line is trying to assign 20 to a variable that does not exist.
4.It can be corrected by writing
extern int i=20;
Hope this helps!
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.