variable in two source file - c

I have read this exam code.
"a.c":
int global_1 = 100;
"b.c":
extern int global_1;
int global_2 = global_1 * 2;
int main()
{
return 0;
}
gcc give “error: initializer element is not constant"
I do not write this code, but I want to know why and how to fix.
Thanks.

The problem you are facing is that in order to initialise a variable (global_2 here) it's value (or all values of what it depends on, in your case global_1) need to be known.
When you initialise a variable in a function then it's value only needs to be known at runtime and that is generally the case or you will get an undefined symbol error during compile or link time.
Globals need to be initialised by the compiler during compile time.
extern int global_1;
Says to the compiler that global_1 exists, but not in this compilation unit. It will be accessible after linking. You can use it in functions, but the linker needs to link it first with an object file that actually contains it.
Thus the compiler is unable to initialise it at compile time resulting in the error you see. Linking comes after compiling.
If you need to initialise globals that reference globals in a different compilation unit then you will need to do this in a function. For example the first stem in main().

The error says it all: Initialisers need to be constants.
To fix this you might like to modify your code like this:
int global_2 = 0;
int main()
{
global_2 = global_1 * 2;

Related

Declare global variable after function

Why do we need to declare global variables before function defining and declaring since we call this function after this variable declaration? Isn't it that compiler read line by line? I mean while calling the function compiler should know what's x.
void function()
{
x += 3
}
int x = 3;
int main(void)
{
function();
return 0;
}
And one more question. I know that we can define function after main function provided we declared this function before main. Then how does main function see these functions after main function? Does the compiler first read the whole file and then run main() or sth?
You can think at the job of the compiler like this; it reads the source file token by token (not exactly line by line) and when sufficient tokens are read, it outputs the translation. It repeats that, until the source file is (correctly) finished: the job of the compiler is done.
For every token the compiler reads, it needs to know what the token represents. If it doesn't know, an error is generated.
So, while compiling your function
void function()
{
x += 3
}
it encounters an "x" but does not know what it represents (an integer? A float? Something else?). -error-.
Why do we need to declare global variables before function defining and declaring
Declaration and Definition are two different things. The compiler needs a declaration in order to know how to manage an identifier; the real definition can be somewhere else, even in another source (or already compiled) file.
And one more question. I know that we can define function after main function provided we declared this function before main. Then how does main function see these functions after main function? Does the compiler first read the whole file and then run main() or sth?
As explained before, all the compiler needs is a declaration, so it can output correct (object) code. If you declare function(), then define main(), then define function(), the compiler has enough to generate correct output, which will consist of code for main() and code for function() (we can say "in this order"). The next step, the linker, will take care to connect these two functions.
The definition of function() could also be absent: the compiler still would generate correct code for main(); the linker would instead complain, unless you tell it where to find the definition/implementation of function().
Also note that a definition is also a declaration. So if in your source you declare function() and then main(), you don't need forward declaration.
In the comments I've read that perhaps you are confusing interpreters with compilers - this is true, if you try to compare Python with C: very different beasts. A big difference is compiler vs interpreter, the compiler generates data (object code) but does not link it (and neither runs it). An interpreter instead is a compiler+linker+runtime, all packed together. Normally a compiler generates code that is much faster than the equivalent interpreted program, but to do this it needs accurate informations (precise types and declarations) and often (always?) is less versatile. The interpreter is often more versatile but it can not exploit all the optimizazions a good compiler can do.
Why do we need to declare global variables before function defining
and declaring since we call this variablefunction after this
declaration?
The c language is a strictly typed language. When the compiler processes an identifier it needs to determine its type to generate correct object code.
It is not necessary that a global variable used in a function shall be declared exactly before the function definition. But in any case it shall be declared before its usage in a function.
Here is a demonstrative program.
#include <stdio.h>
void function( void )
{
extern int x;
x += 3;
}
int x = 3;
int main( void )
{
function();
printf( "x = %d\n", x );
}
The program output is
x = 6
Here the variable x declared within the function refers to the global variable x defined after the function.
Then how does main function see these functions after main function?
Does the compiler first read the whole file and then run main() or
sth?
C is a compilation language. It does not run programs. It generates object code that then after some processing by the linker can be run.
In the point where a function is used what the compiler is need is the type of the function that to check whether the function is used correctly. If the function is an inline function then it can substitute its call for the function body It can rebuild the object code when the inline definition in the translation unit will be known.

Using 'extern' for creating array in C

I have used extern for creating an array but seems it's giving me an error
"undefined reference to `callback_Task'"
// test.h
typedef struct {
uint32_t count;
uint32_t total;
} callback_task;
extern volatile callback_task callback[10];
Now in C source file
// test.c
void test_task(void) {
callback[1].count = 1;
callback[1].total = 2;
}
While compiling its giving an error:
undefined reference to `callback' at 'test_task'
An extern declaration doesn't create the array anywhere. It's merely an instruction to the compiler/linker to look for the variable somewhere.
You must define it, without extern, in some translation unit you will be linking your program with.
A good candidate would seem to be test.c, like this:
volatile callback_task callback[10];
void test_task(void) {
callback[1].count = 1;
callback[1].total = 2;
}
TL;DR It's not the compiler, it's the linker complaining about the callback variable M.I.A. status.
To elaborate, a statement like
extern volatile callback_task callback[10];
tells the compiler that "somewhere there exists" a variable callback with type callback_task [10]. It's a "declaration", It does not "define" a variable on it's own. So, the existence is "known", not "proven".
Later, while linker is searching for the "actual" variable, it does not get one, and hence the error.

What is wrong with extern short i; i=2; ? gcc complains type conflict

The following code is similar to that of question Is there a difference between initializing a variable and assigning it a value immediately after declaration? downvoted twice, so I am at risk ;-)
short i;
i = 2;
It does not compile with MinGW and -std=c99 -- why? The first line is a declaration of identifier i, not a definition of an object. However, the identifier has file scope and thus external linkage by default. It may be declared and defined elsewhere. The second line could be an assignment to that object. But gcc complains about a missing type or storage class and --after guessing the type as int-- about a type conflict.
You say that short i; has file scope, which implies to me that it (edit: and the subsequent i = 2;) is outside a function. Outside a function, i = 2; on its own is complete nonsense; as a statement, it cannot appear outside a function. (edit) As statements cannot appear outside functions, the "assignment" must be a definition. In old C code, a definition without a storage class was an int definition, so your code is equivalent (under those rules, which it looks like GCC is applying) to:
short i;
int i = 2;
which of course is complete nonsense to a C compiler. (end edit)
You can get more-or-less the effect you're after by defining and initializing:
short i = 2;
This does not work if you merely wish to declare an external variable; in that case, put the initialization in the file with the definition, or in one of your functions (as below).
extern short i;
int main(int argc, char **argv) { i = 2; /* more code */ }

initializing static variable with a function call gives compilation error?

#include <stdio.h>
int foo(){
return 1;
}
int main(void) {
static int q = foo();
return 0;
}
Here is a link for the same. This is a C code and not C++. It compiles and run fine in C++ but not C.
This code was getting compilation error. Can someone please explain why is it getting error? Can static members only be initialized by constant values ? In C++ we need to DEFINE static members after declaring them , why is it not required in C ? I couldn't find any thread with similar query or a good answer.
Global and static variables can only be initialized with constant expressions known at compile time. Calling your foo() function does not constitute using a constant expression. Further, the order in which global and static variables are initialized is not specified. Generally, calling foo() would mean that there must be a certain order, because the function can reasonably expect some other variables to be already initialized.
IOW, in C, neither of your code is executed before main().
In C++ there are ways around it, but not in C.
All the static variables are compile time and the function is giving the output at run time so you are initializing a compile time variable with a run time variable which is not possible so it is giving error.
Another example may be as follows
int main()
{
int p=9;
static int x=p;
}
the above code is also gives you compile time error,The cause is same as above.
If you are doing this in C rather than C++ you can only assign static variables values that are available during compilation. So the use of foo() is not permitted due to its value not being determined until runtime.

Multiple declarations and definitions

Content of X.c:
int i;
main ()
{
fun ();
}
Content of Y.c:
int i;
fun ()
{
}
Why does these two files compile with no error ? (using GCC)
But if i use int i = 10; it prints a multiple definition error.
You may be interested in this question and the answers. Keywords: "tentative definition".
Tentative definitions in C99 and linking
Assuming you really want an independent variable called i in each of these two files, you need to prefix them with static in order to give them internal linkage.
static int i = 10;
If you want i to be the same variable in both files, so changes in one affect the other, use the answers you were given 3 hours ago when you asked a variant of the question. If it is to be shared, you need to define the variable in one place.
As to why it didn't cause an error without the init, I think that's because you weren't using the variable until it needed initializing and so the compiler ignored it.
Because there is a difference between a declaration and a definition. int i; does nothing more than introducing a name. int i = 10; on the other hand defines i, hence, a place in the memory must be reserved to store the value it corresponds to. But it is impossible for the compiler to know which value corresponds to i as you want to associate two memory locations with the name i.
This is under the assumption that you link these files against eachother, which is not entirely clear from your explanation.

Resources