Automatic Storage used in a function does not re-initialize the i variable declared using the auto keyword.
Practice.c : main() and func() are in the Practice.c
#include <stdio.h>
main()
{
func();
func();
func();
}
func()
{
auto int i=1;
printf(" i = %d",i);
i=i+1;
}
After compilation when I execute Practice.exe the output is as follows :
i = 1
i = 1
i = 1
Every time main() calls func() i is re-initialized to 1. This is correct as scope of i is within the func() block, and when the control comes out of this block the value of i is lost. So, when I will be calling this func() function for the second time the value of i will be re-initialized to 1.
Check the following New.c Program.
New.c : contains both main() & func()
#include <stdio.h>
main()
{
func();
func();
func();
func();
func();
func();
func();
func();
}
func()
{
auto int i;
printf(" i = %d",i);
i=i+1;
}
Just to be sure, I called the function func() 8 times.
But in New.c, i is not initialized. When I executed this program after compilation, the output of it is as follows :
i = 4201582
i = 4201583
i = 4201584
i = 4201585
i = 4201586
i = 4201587
i = 4201588
i = 4201589
The output shows increment on every call. What is the exact reason behind this ?
The output shows increment on every call. What is the exact reason
behind this ?
Variables with automatic storage allocation are not initialized by default and it is undefined behaviour to access an uninitialized variable. This means the behaviour of your second program cannot be reasoned out.
Also, note that the default stororage class of variables in function scope is automatic. Therefore, you don't need the auto keyword to qualify the definition of i.
// in function scope
auto int i;
// equivalent to
int i;
Also, it's wrong to say
So, when I will be calling this func() function for the second time
the value of i will be re-initialized to 1.
The variable i is not re-initialized. It goes out of scope once the function containing it returns. When the function is called again, it's again allocated on the stack. This does not mean that it is allocated on the same memory address.
Also, you need to take care of the return type and parameter list of the functions. The implicit return type is int and empty parameter list means no information is available about the number and type of arguments which means the function takes a fixed but unknown number of arguments of unknown type. You should always explicitly mention void in the parameter list to mean that the function takes no argument.
#include <stdio.h>
// prototype of the function func
void func(void);
// main should have one of the below signatures -
// int main(void); or
// int main(int argc, char *argv[]);
int main(void)
{
func();
func();
func();
}
// explicitly mention void in the
// parameter list to mean the function
// takes no argument
void func(void)
{
// using auto keyword is redundant because
// local variables have automatic storage allocation
int i = 1;
printf("i = %d", i);
i = i + 1;
}
In the second case, you make use of i without ever having initialized it.
The value is therefore undefined by the language. The fact that you see a pattern of the value incrementing is an artifact of the particular compiler you are using.
In the first iteration, you have a random-seeming value that happens to be at the memory location that i represents. Your function increments the value at that memory location, then that memory location happens to be used for subsequent calls.
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.
#include <stdio.h>
int main()
{
static int i = 5; // here
if (--i){
printf("%d ", i);
main();
}
}
Output: 4 3 2 1
#include <stdio.h>
int main()
{
int i = 5; // here
if (--i){
printf("%d ", i);
main();
}
}
Output: 4 4 4 4... (Segmentation fault)
Any idea how static int variable is taken into account only once and int is taken over and over again?
When you declare a static variable in a function, the function "remembers" the last value of the variable even after it terminates.
void Foo() {
static int x = 5;
}
In the example above, you are telling the compiler that x shall be "remembered" and has an initial value of 5. Subsequent calls to Foo() does not reassign x a value of 5, but uses the previously remembered value.
In contrast:
void Bar() {
int x = 5;
}
Here, you are telling the compiler that everytime Bar() executes, a new variable x is to be created on the stack and assigned a value of 5.
A variable declared as static inside of a function retains its value each time the function is called. It is initialized only once, when the function is first called. So when the function calls itself the value of i is retained from the prior call.
A local variable that is not static is specific to a given call of a function, so each time the function is called a new copy of the variable is created and initialized. This results in i being 5 each time, which in turn results in infinite recursion leading to a stack overflow and a core dump.
#include <stdio.h>
#include <stdlib.h>
int f(int x) {
return x;
}
int main ( int argc,char * argv[]) {
int a=4;
f(a);
printf("PASSED!\n");
return 0;
}
What happens when you call f(a) without assigning it to anything?
What happens when you call a function with return value without assigning it to any variable?
The return value of a function need not be used or assigned. It is ignored (usually quietly).
The function still executes and its side effects still occur.
Consider the 3 functions: int scanf(), int f(), and int printf(), their return values are all ignored yet the functions were still executed.
int a=4;
scanf("%d", &a);
f(a);
printf("PASSED!\n");
It is not good to ignore return values in robust code, especially scanf().
As commented by #Olaf, a warning may be enabled by some compilers.
Explicit ignoring the result of a function is sometime denoted with (void) to quiet that warning.
(void) f(a);
Using your example, we can look at how it evaluates line by line. Starting in main.
int a=4;
We now have a variable a with the value 4.
f(a);
So now the function f is called with a, which has a value of 4. So in the function f, the first parameter is named x and it just returns that parameter x.
So the evaluation of
f(a);
is just
4;
And a program like this compiles and runs perfectly fine.
int main(int argv, char *argv[]) {
1 + 1;
return 0;
}
What happens when you call f(a) without assigning it to anything?
--> Nothing at all.
What happens when you call a function (which has return value) without assigning it to anything?
-->The function will be executed, either make no sense like your case or make a lot of senses like modifying a static variable or a global variable. The return value will be ignored.
The return value will normally be stored in a register and will not fade.
It will be overwritten when the register is needed by the compiler.
If the function is inline it may be detected by the compiler that the value isn't used and ignore the value from being computed at all.
I know that If a function has no argument & only return type (say int), then I can change my int variable by assigning the function to my variable as below,
main()
{
int var_name;
var_name = func();
printf("My variable value is updated as : %d", a);
}
func()
{ return 100; }
Also I know that If I have my function's return type as void, with no arguments, then I can only print the value inside the function itself and cannot return anything in turn.
But, my doubt is, is there anything else that I can do to update my var_name by calling a function with no arguments & no return type ?
ie., void func(void); by using something like pointer concepts ??
I could not able to find the exact answer for the same by my searches among so many websites.. I will be very grateful if someone can help me out finding whether I can do it by this way or not,.
Thanks,.
It is possible to modify a local variable in main, from a function with no arguments and no return value, if there's a global pointer to it:
#include <stdio.h>
int *p;
void func() {
*p = 6;
}
int main() {
int a = 5;
p = &a;
func();
printf("a = %d\n", a); // prints: a = 6
return 0;
}
There's no good way to do that. If you want the function to modify a local variable, you should probably change the function so it either returns a value that you can assign to the variable, or takes the variable's address as an argument.
But if you don't mind writing some ugly code, you can define a global (file-scope) pointer variable, assign the local variable's address to the global pointer, and then use that to modify the variable inside the function.
An example:
#include <stdio.h>
int *global_pointer;
void func(void) {
*global_pointer = 42;
}
int main(void) {
int local_variable = 0;
global_pointer = &local_variable;
func();
printf("local_variable = %d\n", local_variable);
}
It's very easy to shoot yourself in the foot his way. For example, if you refer to the pointer after the calling function has terminated (and the local variable no longer exists), you'll have undefined behavior.
This technique can actually be useful if you need to make a quick temporary change in a body of code in which you can't make major interface changes. Just don't do it in code that will be maintained by anyone else -- and wash your hands afterward.
You can have global variable
int var_name;
void func();
int main()
{
func();
printf("%d\n",var_name);
}
void func()
{
var_name = 20;
}
But if your variable is local to main() then this can't be done.
There are two ways to modify the value of var_name.
Make changes in the calling function and return the value.( which you have already shown)
Pass the address of the var_name to the function and have pointer as arguement in the func(int *p) and modify the value inside the func()
Thats it!! No other way this can be done.
I'm trying to use a separate function to input data using scanf() (outside of main). This new function is supposed to print a line and then receive input from the user. However something appears to be going awry between the scanf in the function and the printf() function in the main that I am testing it with.
I believe that I am receiving a pointer from the function but certain compiler warning are making me wonder if my assumption about the pointer is even correct.
I am confused by the output of this code:
#include <stdio.h>
void set_Info(void);
int main()
{
int scanNum = 0;
set_Info();
printf("%d", &scanNum);
return 0;
}
void set_Info(void) /* start of function definition */
{
int scanNum;
printf("Scan test, enter a number");
scanf("%d",&scanNum);
}
If I provide a number, say 2, the result of the printf statement in the main() is:
2665560
Now, in so far as I am able to tell that output appears to me like a memory address so what i attempted to do to fix that is dereference the pointer in main like so :
int scanNum = 0;
int scanNumHolder;
set_Info();
scanNumHolder = *scanNum;
printf("%d", &scanNumHolder);
I believe that this code makes scanNum variable to become assigned to the dereferenced value of scanNum. However I get the same output as above when I do this. Which leads me to believe one of two things. Either that I am not correctly dereferencing scanNum, or that scanNum is not in fact a pointer at all in this situation.
The most common error I receive from the compiler is:
error: invalid type argument of unary ‘*’ (have ‘int’)
Which makes sense, I suppose, if I'm attempting to treat an int value as a pointer.
If it is the case that scanNum is not being dereferenced correctly, how can I achieve this?
Thank you for the help
*Update
Thanks for the help.
Just to recap
My set_info function needs to be passed an address parameter. The reason an address parameter has to be used is because the local memory of a function is erased after the function call ends. So in order to do work a variable declared in the main function, I pass the address of the variable in question so that when the function ends the changes are not lost.
Inside the main function, when set_info is called with &scanNum as the argument, it passes a reference tp the variable so that it can be assigned the value generated by the scanf statement in the function.
I realize that what I was doing wrong as correctly pointed out by the awesome people of SO, is that I am trying to call set_info like it returns a value but in fact changes the variable like I actually want.
Thanks again for the help!
This function:
void set_Info(void)
{
int scanNum;
scanf("%d", &scanNum);
}
reads the integral number from the standard input and stores it into scanNum variable, which is local variable with automatic storage duration that exists only within the scope of this function.
And the body of your main:
int scanNum = 0;
set_Info();
printf("%d", &scanNum);
defines a local variable called scanNum, then calls a set_Info() function which doesn't affect scanNum defined in main in any way and then it prints the address of scanNum variable.
This is what you are trying to do:
void set_Info(int* num)
{
// read an integer and store it into int that num points to:
scanf("%d", num);
}
int main()
{
int scanNum = 0;
// pass the address of scanNum to set_Info function so that
// changes to scanNum are visible in the body of main as well:
set_Info(&scanNum);
printf("%d", scanNum);
return 0;
}
I also recommend you spend more time reading some book with C basics before you'll continue programming :)
I would pass in the variable into your set_Info function, so that it knows where to save the data. This would then allow you to scan multiple values, and you would simple increment the pointer. Be sure to pass the variable address into set_Info() using &variableName, since that function expects a pointer
#include <stdio.h>
void set_Info(int *pScanNum);
int main()
{
int scanNum = 0;
set_Info(&scanNum);
printf("%d", scanNum);
return 0;
}
//Pass in the pointer to scanNum
void set_Info(int *pScanNum)
{
printf("Scan test, enter a number");
scanf("%d",pScanNum);
}
Get rid of your ampersand! Printf wants an integer not a pointer.
printf("%d", scanNum);
And as liho said, you need to return scanNum from set_info so you can get at it outside of the function.
int scanNum = set_Info();