#include <stdio.h>
int call()
{
extern int b;
b=10;
printf("%d",b);
}
int main ()
{
int b=8;
call();
return 0;
}
Why is throwing an error like these do I get the following linker error:
/tmp/ccAsFhWX.o:meka.c:(.text+0x7): undefined reference to `_b' collect2: ld returned 1 exit status
I wanted to change the b value in the other function using extern keyword but it gives me an error.am i right in doing so ?
Declaring the extern int b declares it as.... extern. It must be defined elsewhere. If it isn't, drop the extern keyword?
I think you wanted a global variable:
#include <stdio.h>
static int b;
int call()
{
b=10;
printf("%d",b);
}
int main ()
{
b=8;
call();
return 0;
}
If you declare the global b as extern you gain the possibility (and the duty) to define it elsewhere (perhaps in another translation unit (helpers.c) or a library (helpers.a) etc.)
In the C programming language, an external variable is a variable defined outside any function block. Please read about extern variables (here, for example).
Also, variables have scopes. For example, it can be a local variable, a global variable etc. You can read more about that here.
So what you have done here is declared a function scope variable in function call () without defining it using the power of extern keyword. In other words, simply tells the compiler that variable already exists somewhere. On top of that, you declared and defined another function scope variable in function main (), which has the same name. It is important to understand that those variables are totally different. So at the end of day, when you link your program, the definition of the variable b for function call () is not found. You declared it but never defined, remember?
Here are possible solutions. Do not declare multiple b variables as that was clearly not your intent. Stick with a single declaration and definition:
#include <stdio.h>
extern int b;
void call()
{
b = 10;
printf("%d\n",b);
}
int b = 8;
int main () {
call();
return 0;
}
But global variables are usually very bad - global scope makes them extremely pipeline unfriendly, introduce threading issues etc. So you must look into something like this:
#include <stdio.h>
void call (int *b)
{
printf ("%d\n", *b = 10);
}
int main () {
int b = 8;
call (&b);
return 0;
}
I'd also recommend you read the following question and answers here. It explains a lot about extern variables in C.
And by the way, you function call () is declared with int return type but returns nothing.
Hope it helps!
To change the "b" in main(), you must pass a pointer to "call" like call (&b) and then do
void call (int *b) {
*b = 10;
printf("%d",*b);
}
Related
This question already has answers here:
Error "initializer element is not constant" when trying to initialize variable with const
(8 answers)
Closed 2 years ago.
Hi i have a test code for calling malloc as below:
#include <stdio.h>
#include <stdlib.h>
int *p;// = (int*)malloc(sizeof(int));
int main() {
//...
}
Of course this code will be fail when compile with the error: initializer element is not constant and i have referenced this question: Malloc function (dynamic memory allocation) resulting in an error when it is used globally. They said that we have to use malloc() in side a function. But if i change my code to:
#include <stdio.h>
#include <stdlib.h>
int *p;
static int inline test_inline(int *x) {
printf("in inline function \n");
x = (int*)malloc(sizeof(int));
return x;
}
test_inline(p);
int main(){
//...
}
As the definition of inline function: "Inline Function are those function whose definitions are small and be substituted at the place where its function call is happened. Function substitution is totally compiler choice." So this mean we can substitute the inline function test_inline in above example with the code inside it and it means we have call malloc() in global ? Question 1: is this wrong about inline or malloc() ?
Question 2: In the link i give about malloc function dynamic there is an answer said that "Not only malloc, u can't call any function as you have called here. you can only declare function as global or local there" but i see that we still can call function in global and in global we can initialization not only declaration as below:
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1;
int test() {
printf("hello");
}
test();
int main() {
//...
}
So this mean in the global we still can declaration and initialization and call function. But when we compile the above code it has a warning that warning: data definition has no type or storage class So why we have this warning with variable b ? I do not see any thing which inconsequential here. And with the line test(); i have call a function outside main(), i know this make no sense because we never run test() but i have no problem, stil build success. So back to question 1 about the malloc(), i think with the answer that "we can not call a function in global or can not initialize", i think it is not true. Is there any explain more reasonable?
Please refer to the comments.
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1; //this is only allowed, because the previous line is a tentative definition. [1]
int test() {
printf("hello");
}
test(); // this is taken as a function declaration, not a function call [2]
int main() {
//...
}
Case [1]:
Change you code to
int b = 5; // not a tentative defintion.
b = 1; // this assignment is not valid in file scope.
you'll see an error.
Case [2]:
If the signature of the function differs, you'll again see an error. Example: try the below:
float test( int x ) {
printf("hello");
return 0.5;
} //return changed to float, accepts an int as paramater.
test(); //defaults to int and no parameter - conflict!!
this will produce the error for conflicting types.
So, bottom line, no assignment, function call - all in all, no code that needs to execute at runtime, can be put into file scope. The reason behind that being, unless it's contained in a function that's called from main(), there's no way to know when / how to execute it.
You're not calling functions "globally".
Taking your example:
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1;
int test() {
printf("hello");
}
test();
int main() {
//...
}
In C types default to int.
So the lines
int b;
b = 1;
are basically
int b;
int b = 1;
and the lines
int test() {
printf("hello");
}
test();
are just
int test() {
printf("hello");
}
int test(); // -> this is just a matching declaration
Have a look at:
https://godbolt.org/z/3UMQAr
(try changing int test() { ... to char test() { ... and you get a compiler error telling you that those types don't match)
That said, you can't call functions there. Functions are called at runtime by your program (especially malloc, which is asking your OS to allocate memory for you). I'm not a C expert here but as far as I know C doesn't have constexpr functions, which would be the only "exception".
See: Compile-Time Function Execution
Question 1: is this wrong about inline or malloc()
kind of: malloc does have to be called in a function, but the variable it works on can be declared global. i.e. int *pointer = NULL;//global scope
then pointer = malloc(someByteCount);//called within function. Now, pointer is still global, but also has a memory address pointing to someByteCount bytes of memory.
Question 2: In C, all functions are defined on the same level of a .c file, just like main(void){...return 0}, but all functions (except main(void)) must be called within the {...} of other functions, so in short, functions cannot be called from global space.
Illustration for Q2:
//prototypes
void func1(void);
void func2(void);
void func3(void);
int main(){
int val = test_inline(p);//...
}
int main(void)
{
//legal
func1();
func2();
func3();
return 0;
}
//not legal
func1();
func2();
func3();
//definitions
void func1(void)
{
return 0;
}
void func2(void)
{
return 0;
}
void func3(void)
{
return 0;
}
Errors in syntax of your example (see comments):
int *p = NULL;//initialize before use
static int inline test_inline(int *x) {
printf("in inline function \n");
x = (int*)malloc(sizeof(int));
printf("%p\n", x);
return 0;
//return x;//function returns int, not int *
}
//... test_inline(p);//must be called in a function
int main(void){
int val = test_inline(p);//function declaration returns int, not pointer
return 0;
}
This code compiles, and runs, but as noted in comments, usefulness may be lacking.
Question 1: is this wrong about inline or malloc() ?
Neither. Your understanding of inline is incorrect. The function call may be replaced with an inline expansion of the function definition. First, let's fix the function definition because the return type int doesn't match the type of what you're actually returning:
static inline int *test_inline( int *x )
{
printf( "in inline function\n" );
x = malloc( sizeof *x );
return x; // x has type int *, so the return type of the function needs to be int *
}
If you call this function like so:
int main( void )
{
int *foo = test_inline( foo );
...
}
what the compiler may do is substitute the function call with the assembly language equivalent of the following:
int main( void )
{
int *foo;
do
{
printf( "in inline function\n" );
int *x = malloc( sizeof *x );
foo = x;
} while( 0 );
...
}
Nothing's happening "globally" here. The substitution is at the point of execution (within the body of the main function), not at the point of definition.
Question 2: In the link i give about malloc function dynamic there is an answer said that "Not only malloc, u can't call any function as you have called here. you can only declare function as global or local there" but i see that we still can call function in global and in global we can initialization not only declaration as below:
In the code
int test() {
printf("hello");
}
test();
the line test(); is not a function call - it's a (redundant and unnecessary) declaration. It does not execute the function.
Here are some excerpts from the language definition to clarify some of this:
6.2.4 Storage durations of objects
...
3 An object whose identifier is declared without the storage-class specifier
_Thread_local, and either with external or internal linkage or with the storage-class
specifier static, has static storage duration. Its lifetime is the entire execution of the
program and its stored value is initialized only once, prior to program startup.
Bold added. Any variable declared outside the body of a function (such as p in your first code snippet) has static storage duration. Since such objects are initialized before runtime, they cannot be initialized with a runtime value (such as the result of a function call).
6.7.4 Function specifiers
...
6 A function declared with an inline function specifier is an inline function. Making a
function an inline function suggests that calls to the function be as fast as possible.138)
The extent to which such suggestions are effective is implementation-defined.139)
138) By using, for example, an alternative to the usual function call mechanism, such as ‘‘inline
substitution’’. Inline substitution is not textual substitution, nor does it create a new function.
Therefore, for example, the expansion of a macro used within the body of the function uses the
definition it had at the point the function body appears, and not where the function is called; and
identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a
single address, regardless of the number of inline definitions that occur in addition to the external
definition.
139) For example, an implementation might never perform inline substitution, or might only perform inline
substitutions to calls in the scope of an inline declaration
All this means is that the inlined code behaves like it was still a single function definition, even if it's expanded in multiple places throughout the program.
In C, is there a way to ensure a function is called only once without using pthread_once?
The following works in C++ but apparently not in C because initialization of a static variable must be to a constant (as I interpret the compile error)
// main.c
int func()
{
return 42;
}
int main( int argc, char* argv[] )
{
static int i = func();
return 0;
}
I thought using the comma operator might get around this, but that doesn't work either:
// main.c
int func()
{
return 42;
}
int main( int argc, char* argv[] )
{
static int i = ( func(), 42 );
return 0;
}
Compilation of both results in the following compile error:
> gcc -g main.c
main.c: In function 'main':
main.c:10:18: error: initializer element is not constant
Are there any ways to circumvent this and ensure a function is only invoked once (from a calling function scope) without using pthread_once?
To be specific, I don't want to return early from func() if it has been called once, I'm interested in compile-time assurance that func() is only called once from a calling function scope - i.e. similar to how C++ would handle the above code.
(In other words, the above code is legal to a C++ compiler, which ensures func() is only called once - is there an equivalent way to do this in C without pthread_once?)
EDIT:
I didn't phrase this ideally in the original post: I was looking for a solution that didn't involve wrapper/helper functions or variables; i.e. I was curious to know if there was a construct in the C language that allowed this situation to be handled equivalently to how it is handled in C++. jxh's solution fits that best, making use of a gcc extension.
No way to leverage static variable initialization
Your attempt to leverage static variable initialization will not work. C only allows static variable to be initialized with constants, so a function call is out.
One shot call of a function at program start (or library load)
It is not clear why you want the onetime call, but if it's okay to do it at program startup, there is a GCC specific solution.
You can assign the constructor attribute to the function.
#include <stdio.h>
__attribute__((constructor))
void func()
{
puts(__func__);
}
int main () {}
This suggestion does not perform your specific ask:
I'm interested in compile-time assurance that func() is only called once from a calling function scope ...
Instead, it assures the function is called exactly once when the program starts (or when the library it is a part of is loaded).
Use a static variable as a guard
If you need to control when the function is called in the exact way initialization of a static variable local to a function is initialized, then you could use a static variable to track whether your one shot function has been called yet with its own static variable. Other answers have already described how to accomplish this, but for completeness:
void caller_of_func()
{
static bool func_already_called;
if (!func_already_called) {
func();
func_already_called = true;
}
/*...*/
}
Use a function pointer!
Another way to accomplish your goal would be to call the function through a function pointer. The initial call to the function would do the real work, and then switch the function pointer to point to a function that does nothing.
void nothing_func(int *x);
void initial_func(int *x);
void (*func)(int *x) = initial_func;
void initial_func(int *x) {
*x = 42;
puts(__func__);
func = nothing_func;
}
void nothing_func(int *x) {
puts(__func__);
}
void foo(void) {
static int x;
func(&x);
printf("%s: %d\n", __func__, x);
++x;
}
int main(void) {
foo();
foo();
}
You can wrap your function in another function which checks a static variable and calls func only if it hasn't been called before as -
static int func_internal() {
...
}
int func() {
static int guard = 0;
if (guard)
return 0;
guard = 1;
return func();
}
Now, expose only func to other modules.
You can do this with a static flag.
// main.c
int func()
{
return 42;
}
int main( int argc, char* argv[] )
{
static int initialized = 0;
if(!initialized) {
func();
initialized = 1;
}
}
The first time through the calling code, the initialized flag is unset, so the function will be run. For any subsequent calls, the flag is already set and so the function will not be called.
See the comments to see what is being referred as declaration.
If the whole variable declaration part was missing, what would be the problem?
Appears that variable definition and initialization either simultaneously or separately like in the example would suffice.
#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;
}
If the declaration was missing then it would create no problem in main function since the locally defined variables i.e. a,b,c,f will be used in the functionality of main till its scope ends.
The declaration merely tells that the definition lies elsewhere (in some other .c file) or the definition lies after the function main in the same .c file.
There will be no problem here if the mentioned declaration is missing.
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
This tells the compiler that these variables are defined somewhere else(in another file).
/* variable definition: */
int a, b;
int c;
float f;
This is where you define variables but they are not the same as the external variables you declared since they are in the inner scope of the main function.
The scope is the place where variables live. extern keyword notes that the scope is global.
You can define variables with the same name in an inner scope and access only them as you did in the main function but it's not a good practice.
void foo()
{
int a = 5;
printf("%d\n", a); // 5
// Creating an inner scope
{
int a = 20;
printf("%d\n", a); // 20
}
printf("%d\n", a); // 5
}
The correct way to use the extern keyword with variables is like this.
//h1.h
extern int global_var; // Declaration of the variable
//c1.c
#include h1.h
int global_var = 0; // Definition of the global var. Memory is allocated here.
//main.c
#include h1.h
int main()
{
printf("global var value is %d\n", global_var); // use of the var defined and
// initialized in c1.c
return 0;
}
This program will print 0 since the variable is defined and initialized in c1.c.
Extern extends the visibility of the C variables and C functions. so that lets the compiler know that there is another place that those vars are declared and memory was allocated for them elsewhere.
for example in another c file.
if you compile a c file containing a global var for example:
int c = 5;
and you create a function on you c file that uses this c var, for example:
int someFunc(void){
return c;}
if you run someFunc in your main and print its return value, you will get 5. but you must compile both c files together.
in your program, you only use the locally allocated var declared in your main function.
When it comes to simple variables, there is really no difference between the declaration and definition. There is a difference when it comes to structs and functions. Here is an example:
// Declarations
struct myStruct;
int foo();
int main()
{
...
}
// Definitions
struct myStruct {
int a, b;
};
int foo() {
return 42;
}
In your case, you are hiding the previous declarations so that they are not accessible before the end of the scope. This is commonly called shadowing. It's basically the same thing as this:
int main()
{
int i=0;
printf("i: %d\n", i);
{
int i=42; // Now the previous i is inaccessible within this scope
printf("i: %d\n", i);
}
// And now it is accessible again
printf("i: %d\n", i);
}
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.
How can I access a shadowed global variable in C? In C++ I can use :: for the global namespace.
If your file-scope variable is not static, then you can use a declaration that uses extern in a nested scope:
int c;
int main() {
{
int c = 0;
// now, c shadows ::c. just re-declare ::c in a
// nested scope:
{
extern int c;
c = 1;
}
// outputs 0
printf("%d\n", c);
}
// outputs 1
printf("%d\n", c);
return 0;
}
If the variable is declared with static, i don't see a way to refer to it.
There is no :: in c but you can use a getter function
#include <stdio.h>
int L=3;
inline int getL()
{
return L;
}
int main();
{
int L = 5;
printf("%d, %d", L, getL());
}
If you are talking about shadowed global var, then (on Linux) you can use dlsym() to find an address of the global variable, like this:
int myvar = 5; // global
{
int myvar = 6; // local var shadows global
int *pglob_myvar = (int *)dlsym(RTLD_NEXT, "myvar");
printf("Local: %d, global: %d\n", myvar, *pglob_myvar);
}
If you want your code to look sexy, use macro:
#define GLOBAL_ADDR(a,b) b =(typeof(b))dlsym(RTLD_NEXT, #a)
...
int *pglob_myvar;
GLOBAL_ADDR(myvar, pglob_myvar);
...
Depending on what you call shielded global variable in C, different answers are possible.
If you mean a global variable defined in another source file or a linked library, you only have to declare it again with the extern prefix:
extern int aGlobalDefinedElsewhere;
If you mean a global variable shadowed (or eclipsed, choose the terminology you prefer) by a local variable of the same name), there is no builtin way to do this in C. So you have either not to do it or to work around it. Possible solutions are:
getter/setter functions for accessing global variable (which is a good practice, in particular in multithreaded situations)
aliases to globals by way of a pointer defined before the local variable:
int noName;
{
int * aliasToNoName = &noName; /* reference to global */
int noName; /* declaration of local */
*aliasToNoName = noName; /* assign local to global */
}
what is a "shielded global variable" in pure C?
in C you have local variables, file local/global variables (static) and global variables (extern)
so file1.c:
int bla;
file2.c
extern int bla;
Yet another option is to reference the global before defining your local, or at least get a pointer to it first so you can access it after defining your local.
#include <stdio.h>
int x = 1234;
int main()
{
printf("%d\n",x); // prints global
int x = 456;
printf("%d\n",x); // prints local
}