I'd like to understand which mistake i did in the following example. There are three file: main.c, libreria_mia.c and libreria_mia.h.
// main.c
#include <stdio.h>
#include "libreria_mia.h"
int x = 5;
int main()
{
int y = quadrato();
printf("%d\n", y);
return 0;
}
// libreria_mia.h
extern int x;
int quadrato(void);
// libreria_mia.c
int quadrato(void)
{
x = x * x;
}
Error:
libreria_mia.c:5:2: error: ‘x’ undeclared (first use in this function)
Thank you for your time.
When you compile libreria_mia.c, the compiler does not automatically know about libreria_mia.h or the declarations within it. To provide a declaration for x while compiling libreria_mia.c, libreria_mia.c must include a header that declares x or have a declaration of x directly in libreria_mia.c.
Additionally, it is conventional for a header named file.h to declare things defined in file.c (not necessarily all things defined in file.c, just those intended to be used outside it). But you have x declared in libreria_mia.h but defined in main.c. Normally, one would either define x in libreria_mia.c or declare it in main.h, and usually the former as main.c is more commonly a user of all other things in the program rather than a provider.
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;
)
I wrote an add function for int in Add.c. Then, I passed real numbers to this add function in Main.c. The codes are shown as follows.
If I have declaration of add function before calling it, the answer is correct as 30. However, if the declaration does not exist, the answer is incorrect. Why?
Add.c
int add(int x, int y) { return x + y;}
Main.c
#include<stdio.h>
int add(int, int); // If this does not exist, the answer is not 30.
int main(void) {
printf("%d\n", add(10.5, 20.5));
}
Without the declaration, which is more specifically a prototype (a declaration with specified parameter types), you're relying on an implicit prototype-less declaration of the function (which is now an obsolescent feature of C).
The implicit prototype for function f is int f()—a function returning int and taking an unspecified number of parameters.
The way functions without prototypes are called is the arguments are promoted (lesser than int integer types to int and floats to doubles) and passed to the function in an implementation-defined way. If the arguments don't match the definition, the behavior is undefined (your case).
You could fix this (while still relying on the implicit declaration) by providing explicit casts:
#include<stdio.h>
//nothing (probably will get a compiler warning) or
int add(); /*=params unspecified*/
int main(void) {
printf("%d\n", add((int)10.5, (int)20.5));
}
thereby removing the UB (undefined behavior), or you can include the prototype as you have, which will make the compiler convert passed-in floats to match the expected types (int). In other words, with the prototype, the compiler will insert these casts for you, seeing that a conversion from float to int in (argument) assignment.
The preferred way to solve this is with a prototype included via a header which is also included in the implementation file (Add.c) so as to allow to compiler to verify the call is consistent with the definition.
To make this work, first of all, you have to include the "add.c" file into the "main.c". Coz main.c doesn't know about "add" function in add.c. (Also you should not make '.c' file to add a function or something. Instead use '.h')
Now the solution should look like this...
add.h
int add(int x, int y){
return x + y;
}
main.c
#include<stdio.h>
#include "add.h"
int main(void){
printf("%d\n", add(10, 20));
return 0;
}
Make sure to keep both the files in same directory.
Before using add in Main.c, it needs to know the declaration for this function. Without using function prototype in this case the behavior of the program would be undefined. You can either add a prototype before main as you did or you can create a separate Add.h file and put the prototype there.
In second case you need to add Add.h to both .c files.
Add.h
#ifndef ADD_H
#define ADD_H
int add(int x, int y;
#endif
Add.c
#include "Add.h"
int add(int x, int y) { return x + y;}
Main.c
#include<stdio.h>
#inclide "Add.h"
int main(void) {
printf("%d\n", add(10, 20));
}
I have a very mixed notion of what happens when I compile many files - mostly when it comes to the visibility of things from one file to an other. From what I read, static limits the scope of a variable or function to the file itself. extern does the opposite. From that I would expect to be able and simply read a global extern from any file. That doesn't work in practice though as seen below.
main.c:
#include <stdio.h>
int main(void){
printf("%d\n", b); // b is extern global
return 0;
}
a.c:
static int a = 40;
b.c:
extern int b = 20;
I can't even compile:
> gcc main.c a.c b.c -o test
b.c:1:12: warning: ‘b’ initialized and declared ‘extern’ [enabled by default]
extern int b = 20;
^
main.c: In function ‘main’:
main.c:4:20: error: ‘b’ undeclared (first use in this function)
printf("%d\n", b); // b is extern global
You are doing all wrong.When we writing extern int b it means an integer type variable called b has been declared.And we can do this declaration as many times as needed. (remember that declaration can be done any number of times).By externing a variable we can use the variables anywhere in the program provided we know the declaration of them and the variable is defined somewhere.
The correct way is
main.c:
#include <stdio.h>
extern int b; //declaration of b
int main(void){
printf("%d\n", b); // using b
return 0;
}
b.c:
int b = 20; //definition here
and compile as gcc main.c b.c -o test
I have omitted a.c as it was doing nothing in this example.
To understand more about externs see this site.Its having very good content http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
A variable can be used if it is either declared or defined.
In main.c, there is no declaration of b. You can add
extern int b;
in main.c for the compiler to be able to use b. This declares to the compiler that b is defined somewhere else and it is of type int.
In b.c, you can remove the word extern. Unless qualified with static, it is extern by default.
int b = 20;
Even in b.c, you can use a declaration at the top of the file and define it at the bottom.
extern int b;
//
// ... code that uses b
//
int b = 20;
The extern line simply declares the variable. The last line defines the variable.
When you have a extern variable the compiler knows that the declaration for this variable is here and definition is somewhere else.
So you can do as shown below
some.h
extern int b; /* Declare the variable */
b.c
int b = 20; /* Define the variable */
main.c
#include<some.h>
int main()
{
printf("%d\n",b); /* Use the variable b */
return 0;
}
With this now the file main.c knows the declaration of b since it is there is some.h file.
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.
I got some problem with the following codes particularly in header.c where i can't access the extern int x variable in header.h... Why? Does extern variable in .h not global? How can i use this on other files?
===header.h===
#ifndef HDR_H
#define HDR_H
extern int x;
void function();
#endif
===header.c===
#include <stdio.h>
#include "header.h"
void function()
{
printf("%d", x); //****undefined reference to x, why?****
}
===sample.c===
int main()
{
int x = 1;
function();
printf("\n%d", x);
return 0;
}
The declaration
extern int x;
tells the compiler that in some source file there will be a global variable named x. However, in the main function you declare a local variable x. Move that declaration outside of main to make it global.
The extern keyword say the variable exists but does not create it. The compiler expects that another module will have a global variable with that name, and the linker will do the right thing to join them up.
You need to change sample.c like this:
/* x is a global exported from sample.c */
int x = 1;
int main()
{
function();
printf("\n%d", x);
return 0;
}
extern declares a variable, but does not define it. It basically tells the compiler there is a definition for x somewhere else. To fix add the following to header.c (or some other .c file but only one .c file):
int x;
Note that in main() the local variable x will hide the global variable x.
Indeed extern int x; means x will be defined in another place/translation unit.
The compiler expects to find a definition of x in the global scope somewherelse.
I would reorganise/modify your code like this and get rid of header.c
===sample.h===
#ifndef SAMPLE_H
#define SAMPLE_H
extern int x;
void function();
#endif
===sample.c===
#include <stdio.h>
#include "sample.h"
int x;
void function()
{
printf("%d", x);
}
int main()
{
x = 1;
function();
printf("\n%d", x);
return 0;
}