Still confused with declaration and definition in term of C:
if a header file is like:
#ifndef _BASIC_H_
#define _BASIC_H_
void test();
extern int i; //define or declare
#endif
and two source file f1.c and f2.c contain this header, then one source file need to define the variable "i".
but if the header file is like:
#ifndef _BASIC_H_
#define _BASIC_H_
void test();
int i; //define or declare
#endif
and two source files f1.c and f2.c, contain this header without define the variable "i" in any file, it still goes through when I use the variable.
my questions is when the variable is defined.
Thanks
Defining a variable is when you allocate memory for the storage and maybe assign it a value. Declaring is when you state that a variable with a specific name and type exist, but memory has been allocated for it already.
The use of the extern keyword means that you are declaring the variable but not defining it.
In terms of your specific question, your first example is declaring and your second answer is defining.
Related
I'm getting my sea legs with C, and I need a string literal which is discovered in a main function in one .c file to be accessible in an entirely different .c file.
What I've tried: I'm declaring a pointer to a string literal as extern in a header, defining it on one .c file, and trying to access the literal in a second .c file. Compilation is failing due to lack of definition in the second (accessing) file.
What I've got in a nutshell:
file1.h :
extern char *global;
file1.c :
#include "file1.h"
int main() {
//some code
extern char *global = some_struct->data;
//more code
}
file2.c :
#include "file1.h"
int do_stuff() {
//some code
some_function(global);
//more code
}
I expected this to compile, since global is declared in file1.h, defined in file1.c, and its value accessed in file2.c. Compilation of file2.c fails, however, for undefined variable.
If relevant, the main function in file1.c is always the first function run in the program.
in main
extern char *global = some_struct->data;
is wrong, if you want to assign global do :
global = some_struct->data;
and some where at global scope you need to define global :
char *global;
So for instance main become :
#include "file1.h"
char *global;
int main() {
//some code
global = some_struct->data;
//more code
}
You're close, but not quite there. The global variable must also be defined in the global scope, and you're running into the difference between declaration and definition (which are easy to get the wrong way round but the words don't matter as much as the idea). Normally, your statements that introduce a variable will both declare and define simultaneously, but not so with globals that are shared between modules like this:
In your file1.h, you are correctly declaring the char* variable in the global scope. Anyone who includes this file (e.g. file2.c) will "see" that the variable with that name should exist and all modules will compile cleanly, and the extern keyword makes explicit that you are only declaring this to exist, not creating storage for it yet. That is what you want, because you don't want to accidentally create multiple conflicting global variables with this name. When the compiled modules are eventually linked together, the linker will look for the actual memory storage space set aside for the global and connect all the references up correctly.
But in your case, that won't happen correctly, because although you have declared to the world that this global exists, you haven't yet actually created storage for the variable!
You still need to do this in the global scope (outside the functions) in file1.h:
char * global;
That creates the actual variable with the matching name to the extern declaration, and so the linker will be able to assemble your modules correctly.
So
#include "file1.h"
// Define global:
char * global;
int main() {
// Assign a value to the global variable:
global = some_struct->data;
//more code
}
Note that you don't redeclare the extern or anything in this file, and you don't redefine the type of global inside main, because it already exists, and you can assign to it or look at its value. You also don't use the keyword extern here-- it is the "home" module for this variable.
Declaration and definition are generally just accomplished simultaneously, for example when you declare local variables within a function. Globals that are accessible from different modules rely on splitting the work into the two separate ideas so that both coworkers and the compiler and linker toolchain are not confused by your intentions.
This answer confused me.
If we have two lines in same .c file:
extern int c;
int c;
How is the first line of code a declaration and second a definition?
Aren't both declarations?
How these two lines differ?
The extern keyword is what makes the first line a declaration. It say "this variable exists somewhere". A line like that can appear in a header file.
The second line is a definition because the extern keyword is not present. If you were to have this line in a header file, two source files that include that header will both define that variable and linking those two files will result in a variable redefinition error.
When the program you're writing consists of multiple source files linked together, where some of the variables defined, for example, in source file file1.c need to be referenced in other source files, so this is the reason why using extern.
About your question how these lines differ:
extern int c;
int c;
A variable is defined when the compiler allocates the storage for the
variable while
A variable is declared when the compiler is informed that a variable
exists (and this is its type); it does not allocate the storage for
the variable at that point.
so only int c; is defined while extern int c; is declared .
A definition creates space for a variable:
int c;
Wherever you put this line, either local, global, this says that a new variable c of type int shall come to life.
extern int c;
A declaration says that there is somewhere else some variable c of type int. By using extern, you say that c is defined somewhere else. If you put only an extern declaration without a definition somewhere else, you will have a link error. Using extern is the equivalent of a forward declaration of a function:
/* declaration */
int f(int x);
vs.
/* definition */
int f(int x) {
return x*x;
}
The first means that there is somewhere a function f returning an int and accepting an int as parameter. The latter is the actual function, its code, which also works both as a declaration and a definition.
IMO, this declaration-vs-definition naming is confusing. I hardly remember which one is what, and I usually need to think about it. You should, however, understand the what extern means and what a forward declaration is.
Long story short, defining something means providing all of the necessary information to create that thing in its entirety. However, declaring something means providing only enough information for the computer to know it exists.
Edit: To be clearer: A definition both defines and declares, a declaration ONLY declares. When you are using the extern keyword by definition you are not defining anything. Your confusion stems from the understanding of extern.
In the code below, can it be expained why extern has been used right after the declaration on function pointer.
myfuncs.h
typedef void (*initMyfuncs_t)(Init_t*, CallBacks_t *,result_t*);
extern initMyfuncs_t _initMyfuncs;
and we are using it in myfunc.c file
void *glbfuncs=NULL
glbfuncs = dlopen("glbfuncs.so",RTLD_NOW);
initMyfuncs_t _initMyfuncs=NULL;
_initMyfuncs = dlsym(glbfuncs, "_initMyfuncs");
Usually,we use extern in the files or other header file where we use this function pointer or variable.
Here we have declared extern in header file and using it in same source file.
what is the use of using extern here
And this function pointer is being used in other source files without extern declaration . iam confused with this? Generally, we have a declaration somewhere (somehere.h) and if we use it in some other file(here.h or here.c) we use extern keyword just to get this variable.
I did not quite understand the reason for using extern keyword after typedef.
Why do we use extern after the declaration of fucntion pointer in the same header file.
The extern keyword is needed to distinguish the declaration of a global data object such as a function pointer and the definition of this object.
In a header file, you should only have declarations. Definitions belong in source files and should not be duplicated in different source files. If you put definitions in header files, you end up with multiple definitions of the same symbols at link time. For historical reasons, common linkers accept these multiple definitions if they do not have initializers. Nevertheless, it is considered bad practice and should be avoided.
myfuncs.h
extern initMyfuncs_t _initMyfuncs; // declaration of function pointer
myfuncs.c
initMyfuncs_t _initMyfuncs = some_function; // actual definition of the pointer with optional initializer.
The confusion comes from the typedef of a function pointer, different from a function prototype. A function prototype is a declaration even without an extern keyword.
extern int a;
is the declaraton of a. It is (just) a promise to the compiler a will be around at link-time.
It's actual definition needs to be done elsewhere, typically in a .c file via
int a = 42; /* The initialiser is optional, if missing it will default to '= 0'. */
The above concept is the same for any type.
A header file can be included in many source files. Without the extern keyword, also storage would be alocated. Without the extern keyword in the header file, this storage would be allocated in every source file that includes the header file. At link time, the linker will now complain about multiple symbols (some linkers solve this gracefully).
To avoid this, yet not having to separately declare the objects in a source file, I use the following method:
/* myInclude.h */
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int myGlobalVar;
/* someFile.c */
#include "myInclude.h"
/* main.c */
#define EXTERN
#include "myInclude.h"
This will allocate storage for the object in main.c and declare it as extern in all other souce files including the header file.
i think i got the answer for that
1.without extern in header there would be a redefinition error , if we use the same variable (initMyfuncs_t _initMyfuncs = nullptr;)
Or we can just mention typedef function pointer and initialize a varaible in source file
myfuncs.h
typedef void(*initMyfuncs_t)(int*, int*, int*);
and initiliaze it in source myfuncs.c
initMyfuncs_t _initMyfuncs = nullptr;
and if we need declaration in header file then
myfuncs.h
typedef void(*initMyfuncs_t)(int, int, int);
extern initMyfuncs_t _initMyfuncs;
and initialize it in source file
initMyfuncs_t _initMyfuncs = nullptr;
And finally when this header file is used in any source file, this variable can be used too as we have extern declared in it
In c, it seems to me that everything written outside of a function is already 'extern'.
When, then, exactly do you have to specify a variable as extern?
Does it have to do with definition vs declaration?
Also, is declaring a variable with extern necessary in order to access a variable defined in another file already?
the extern extends the visibility to the whole program, 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.
Declarations of variables at file scope (Not in other files ) are external by default.
In c, it seems to me that everything written outside of a function is
already 'extern'. When, then, exactly do you have to specify a
variable as extern?
this is most probably true for c functions
By default, the declaration and definition of a C function have “extern” prepended with them
For example have one file named file1.c and declared function lilke
int my_function();
There’s an extern present in the beginning which is hidden and the compiler treats it as below.
extern int my_function();
Therefore whenever we define a C function, an extern is present there in the beginning of the function definition.
For C variables
While defining a function, we can prepend it with extern without any issues. But it is not the case with C variables.
If we put the presence of extern in variable as default then the memory for them will not be allocated ever, they will be declared only. Therefore, we put extern explicitly for C variables when we want to declare them without defining them. `
Here is how you would use extern variables.
I have a UART.c:
#include<stdio.h>
#include<string.h>
#include<UART.h>
int UART_Rcv(unsigned char* Rx_Str[], unsigned int len);
int status;
int UART_Rcv(unsigned char* Rx_Str[], unsigned int len)
{
//Some code for implementation of UART receive.
//set status value and return it, May be (SUCCESS or FAILURE?)
return status;
}
Now I have a UART.h
//header guard
#ifndef __UART_H
#define __UART_H
//Some UART related macros
extern int status;
extern int UART_Rcv(unsigned char* Rx_Str[], unsigned int len);
//other externs if any
#endif
Now I have a main.c which is going to use the function and variable declared in UART.c
#include<stdio.h>
#include<string.h>
#include<UART.h>
#define WIMP_OUT_N_GO_HOME (0)
int main(void)
{
unsigned char Received_String[30];
//Some code and may be initialization of UART?
//Flush the Received_String before using it
UART_Rcv(Received_String, 10);
//Some code
return WIMP_OUT_N_GO_HOME;
}
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. So By externing your UART_Rcv() function and the status variable, you hinted your compiler that those are defined outside of the functional block, or may be in a different source, like we did here. the definitions for those will be found at the linker time.
An external variable must be defined, exactly once, outside of any function
I am kind of confused about the whole including header files and declaration of variables.
Files I am using are: main.c, lib.h and lib.c.
main.c
#include "lib.h"
void main(void)
{
// Code here
var++;
}
lib.c
#include <avr/io.h>
#include "lib.h"
void light_led(void)
{
// Code here
}
lib.h
volatile int var;
void light_led(void);
Is this the correct way of making and including your own custom-made libraries?
You should use extern keyword for such cases and not define global variables in headers. Otherwise the linker will throw errors when operating on your header files.
lib.c
#include <avr/io.h>
#include "lib.h"
volatile int var;
void light_led(void)
{
//code here
}
lib.h
extern volatile int var;
void light_led(void);
This way you'll be declaring the global variable in headers and actually defining it in the appropriate source file lib.c.
Note: Notice the difference between declaring and defining a variable. extern keyword allows the variable to be declared in advance without being defined. Had you not defined the variable in lib.c, there would be an error when you tried to use this variable. Since, it is only declared but, not actually defined.
Edit: The whole purpose of static is to declare that a variable is private to the source file that is declared in. Since, extern does the opposite by linking a variable defined in another source file, it defeats the purpose of static. extern says the variable has external linkage static says the variable has internal linkage. An identifier can't have both internal and external linkage.
According to MSND:
When modifying a variable, the static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared).
For more information check below:
Understanding "extern" keyword in C
Why we need "extern keyword in C