Extern not working when not using variable - linker

I created an extern variable called x and variable x doesn't exist in any other file so therefore, the linker should give me an error. If I only put the declaration of the extern variable (extern int x;) and don't actually use the variable, it won't give me any error but when I use the variable, then it will give me an error. Why doesn't the linker give me an error when I only put the declaration?
No Error:
#include <iostream>
extern int x;
int main() {
}
Gives me Error:
#include <iostream>
extern int x;
int main() {
std::cout << x << std::endl;
}

Related

Confusion about the extern keyword and multiple source files

I am trying to fully understand how extern works, so I created 3 files, two of them are source files and the last is a header file. This is what is contained in each of them:
testingfile1.c
#include <stdio.h>
#include "testingheader.h"
int main() {
change();
int my_extern;
printf("\n%d", my_extern);
return 0;
}
testingfile2.c:
#include <stdio.h>
#include "testingheader.h"
void change() {
int my_extern;
my_extern = 15;
printf("%d", my_extern);
}
testingheader.h:
#if !defined(TESTINGHEADER_H)
#define TESTINGHEADER_H
#include <stdio.h>
extern int my_extern;
void change();
#endif
The output of this program is: 15 0. However, I thought that since my_extern is an extern int, if you were to change to the value in one source file, it's value would be changed in all of the other source files. Is this not how extern works, or am I doing something wrong in the code itself?
In both cases remove int my_extern; where you have it, because those become local variables which happen to have the same name my_extern.
extern int my_extern; just means there's an int called my_extern "out there somewhere". So you'd have to declare int my_extern somewhere at file scope, for example like this:
int my_extern = 0;
void change() {
my_extern = 15;
printf("%d", my_extern);
}
In testingfile2.c, the my_extern variable is local to the function and you are not seeing the global my_extern that the extern command is referencing. Of course, you don't have a global my_extern, so that is another problem. You would get a linker error if you actually tried to reference the global my_extern that the extern command is referencing.
The issue is you're re-declaring int my_extern; inside your functions. Therefore, C treats that as a separate variable from the global my_extern.
The statement extern int my_extern; is a declaration that a global int called my_extern will be declared somewhere. You haven't done that. Instead, you've created local my_extern variables.

Division between declaration and definition in other C files

I would like to know how make the division between declaration and definition. I read few related with this topic question but for now I can do this only in basic funtion. The problem is when I try to declare constant global variable in header file and I want use this constant in the function which have declaration in the same place but definition in other files. I have 2 files with .c extension and one with .h extension.
File main_lib.h consist:
#ifndef _MAIN_LIB_H_
#define _MAIN_LIB_H_
const int N_POINTS=10;
struct Point{
int x;
int y;
};
void fill_random(struct Point points[], int n);
void closest(struct Point points[], int n, struct Point* p);
#endif /* _MAIN_LIB_H_ */
File main_lib.c consist:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "main_lib.h"
void fill_random(struct Point points[], int n){
...
}
void closest(struct Point points[], int n, struct Point* p){
...
}
And the last file named main.c consist:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "main_lib.h"
int main()
{
srand(time(0));
struct Point random_points[N_POINTS];
struct Point *p;
p=&random_points[0];
fill_random(p,N_POINTS);
closest(p,N_POINTS,p);
return 0;
}
The question is how to correct this code to run it without error status. Thanks a lot for any help.
The problem is when I try to declare constant global variable in header file ...
how to correct this code to run it without error status(?)
Instead, declare extern in main_lib.h #Scheff. This would be the same if the global variable was non-const or volatile.
// const int N_POINTS=10;
extern const int N_POINTS;
Define it once and only in main_lib.c
// add
const int N_POINTS=10;
A method I often use is:
// lib.h
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN int myInt;
// lib.c
#include "lib.h"
// main.c
#define EXTERN
#include "lib.h"
myInt will now be known in all modules in which lib.h is included but will only be declared once in main.c. Usefull when you have lots of includes.

Alternative declarations of a variable depending on an if condition

I would like to have as, if i is 1 then a as int type otherwise as char type,but when i compile this code then it encounters below error:
> 1.c: In function ‘main’:
> 1.c:18:16: error: ‘a’ undeclared (first use in this function)
> if(a)
> ^
> 1.c:18:16: note: each undeclared identifier is reported only once for each function it appears in
#include <stdio.h>
#define macro
void main()
{
int i=1;
#ifdef macro
if (i==1)
{
int a;
}
else
#endif
{
char a;
}
if(a)
{
printf("INDOE ");
}
}
i would like to have as, if i is 1 then a as int type otherwise as char type
Stop right here, compiled C code doesn't know about types, so you can't set a type at runtime -- it's already "hardcoded" the time you compile your program.
Side note:
{
char a;
}
if(a)
The braces give the variable a scope, so after the closing brace, a doesn't exist any more.
There are many ways to solve this, they all involve that you store your own type information. Rough idea:
enum mytype { MT_INT, MT_CHAR };
struct myvalue {
enum mytype type;
union {
int a_int;
char a_char;
};
};
[...]
struct myvalue x;
// [...]
if (i==1) x.type = MT_INT;
else x.type = MT_CHAR;
// [...]
Then in each access of x.a_int or x.a_char, check x.type first to know which member to access.
Scope of a variable in C is limited to the block you have declared it. The int a is available only within the if. And the char a is available only within the else
Search about "scope" concept. A variable, in C, defined in a scope will not be accessible outside it or in a scope above, but is accessible on a scope below.
It looks like you want your condtional to be handled by the preprocessor. eg.
#include <stdio.h>
#define i 1
#if i
#define ATYPE int
#else
#define ATYPE char
#endif
int main(int argc, char* args)
{
ATYPE a;
printf("%d\n", sizeof(a));
}
I certainly wouldn't recommend #define'ing i, but this looks a bit like what you're trying to do.

Understanding how extern works

The way I understand extern is that we are able to declare a variable anywhere in a program and use it, but we can just define it once. I am getting an error in the following program.
hello.c
#include <stdio.h>
#include "function.h"
extern int c;
int main()
{
int c;
c=10;
printf("%d\n",c);
printExternValue();
return 0;
}
function .h
void printExternValue();
function .c
#include "function.h"
#include "stdio.h"
extern int c;
void printExternValue()
{
printf("%d\n",c);
}
I expect this program to print out:
10
10
But it's not doing so since it's giving an error. I re-declared the variable c in the function.c file with the intention of using the value that is stored in the so called external storage.
Error: function.c:(.text+0x6): undefined reference to `c'
I am currently reading a PDF file from tutorialspoints which I think to be very redundant since the intention of creating a variable with the aggregate extern is useless. The right way this should be done is that they define the variables outside the function is that right?
#include <stdio.h>
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
int main ()
{
/* variable definition: */
int a, b;
int c;
float f;
/* actual initialization */
a = 10;
b = 20;
c = a + b;
printf("value of c : %d \n", c);
f = 70.0/3.0;
printf("value of f : %f \n", f);
return 0;
}
Variable declread as
extern int c;
is an external declaration that potentially requires an external definiton. "External" in this case means "located outside of any function". Your c declared locally in main() does not fullfill that role.
Since you are using that externally declared variable c in your code you have to define it and define it only once.
You need
int c;
or
int c = 0;
or
extern int c = 0;
it one of your implementation files, at file scope. All of these are definitions. Any of them will define your variable.
Define your variable once in one of your files (to reserve space),
int c = 0;
Declare your variable references everywhere else (in all of your other files) (to reference said space),
extern int c;
But that could be confusing, so name them indicative of the 'global' use,
int glob_a, glob_b;
int glob_c;
float glob_f;
And declare your variable references everywhere else,
extern int glob_a, glob_b;
extern int glob_c;
extern float glob_f;
But you really want to avoid littering you namespace, so when you have a collection of globals, declare a struct that contains them (in a header file probably called globals.h),
typedef struct globals_struct {
int a, b;
int c;
float f;
} globals_t;
And once (in your file main.c that declares main()), you define the struct,
#include globals.h
globals_t globs;
And everywhere else, reference the space,
#include globals.h
extern globals_t globs;
Often, you will see a stanza such as this, where MAIN is only declared in one file,
#ifndef MAIN
extern globals_t globs;
#else
globals_t globs;
#endif
Use your globals,
int my_a = globs.a;
int my_b = globs.b;
int my_f = globs.f;
Notice how you have avoided needless namespace pollution?
Because extern just tells the compiler (actually the linker) that a variable is being defined elsewhere and needs to be linked against.

Compile error on using extern

I wrote a very simple program on C. It compiles and works fine. But if I add extern int x at the functions.h instead of functions.c I get this error
functions.c:3:12: error: use of undeclared identifier 'x'
return x / 2;
^
1 error generated.
I thought the correct place for extern is in the header file.
variables.h
int x = 10;
functions.h
#include "variables.h"
int calculate_items(int d);
functions.c
extern int x;
int calculate_items(int d)
{
return x / 2;
}
main.c
#include <stdio.h>
#include "functions.h"
int main() {
printf("%d", calculate_items(5));
}
No, you can't have an initializer in the header.
It will not work as soon as more than one C file include the same header, there will be multiple declarations.
You should make the variable a global in one of the C files, for instance in main.c, and then just have extern int x; in the files that need to access it (or in headers that they can #include, of course).
In this case, since the variable ends up "belonging to" the main.c file, you should probably add a main.h header that has the extern int x; declaration, and #include that from functions.c and other places that need the variable.
If you don't put extern int x; in functions.c and functions.c doesn't #include anything that declares x, how is it supposed to know what x is?
If you expect some kind of implicit relationship between functions.h and functions.c because they both have names like functions.* then you should just get rid of that expectation.
The normal way to do this is to put the extern int x; in functions.h, then int x=10; in one of the .c files, and #include "functions.h" from all of the .c files that reference x, including functions.c.

Resources