Can a variable be used in an inner function if it was defined in the outer function? or should i modify the inner loop to take a third parameter which would be the array?
Example of the code i'm asking about?
perm_rec1 ( int nr_value , int N)
{
int array[];
secondFunction(int nr_value, int N)
}
The inner function:
secondFunction (int nr_value, int N)
{
int temp = array; //is This possible? Or third parameter?
}
Can a variable be used in an inner function if it was defined in the outer function?
C does not have nested functions, which is the only sense in which the "inner" and "outer" designations would make sense. When one function calls another, as in your example, it is the call that is "inside" the first function, not the called function.
In any event, variables declared at block scope, such as in your example, are visible only within the remainder of the lexical extent of the declaring block. They are not visible in the body of a function called from within that block -- not even if it is the same function, called recursively.
or should i modify the inner loop to take a third parameter which would be the array?
The most natural implementation would be, yes, to give the function a third parameter by which to provide (a pointer to the first element of) the array to that function.
There is no inner function here (nor there is in C). What you have is a function that calls another one; and no you can't access in the callee something that was defined in the caller except if you pass it explicitly as a parameter.
Interpreting what you need, you can use pointers to do that:
#include <stdio.h>
void test ( int *pointer, size_t size)
{
for (size_t i=0; i<size; i++)
{
printf("array[%zu] = %d\n", i, *pointer++);
}
}
int main(void) {
int array[] = { 1, 2, 3, 4, 5};
test(array, sizeof(array)/sizeof(array[0]));
return 0;
}
Any variable declared in the inner block shadows the outer variable declaration.
{
int a = 6;
{
int a = 9;
// won't affect the outer declaration
}
// value of a = 6 here
}
But as you are asking there cannot be any inner function in C. Only we can have inner blocks defined within braces.
Technically speaking, it is actually possible to misuse local variables to access the stack frame of a parent function, yes. But this is a very, very ugly solution, set aside platform-dependent. So just pass it as a parameter.
Related
H.ello just a hobbyist here. I started again C after a little JS detour that taught me closures, oop and other stuff. I usually make small code snippets that I can reference or reuse later. So in the code below is there a reason why the compiler says counter is undeclared, as it is referenced as an argument of the callback function argument?
To make this work,
1. I could make counter a global variable, this works but it is not best practice.
2. I could move caller function inside main, but I'd like to avoid this.
3. pass counter as a 4th seperate pointer argument, however in that case, I don't really know with what voodoo should I invoke the caller function popArr within main.
Generally I'm interested in the technique how to use callbacks with arguments without using global variables or putting everything inside main.
So here is the code:
#include <stdio.h>
// CALLBACKS
/* Caller */
void popArr(int *arr, size_t length, int (*callback)(int *counter)) {
for (size_t i=0; i<length; i++) {
arr[i] = callback(&counter);
printf("arr[%zu] is: %d\n", i, arr[i]);
}
}
/* A simple generator callback saving counter. */
int generator(int *counter) {
*counter = *counter+1;
return *counter*5;
}
/* Main function. */
int main(void) {
int counter = 1;
int arr[10];
popArr(arr, 10, &generator);
return 0;
}
So in the code below is there a reason why the compiler says counter
is undeclared, as it is referenced as an argument of the callback
function argument?
I presume you mean in function popArr(). Yes, of course there's a reason. In popArr(), the symbol counter appears only in the prototype for the callback function, and the scope of that appearance is limited to the prototype in which it appears. There is no symbol with that name in scope in the body of popArr().
The different appearances of the symbol counter in that prototype, in function generator(), and in main() all have different, non-overlapping scope. They are not related to each other, notwithstanding the reuse of the same name.
Generally I'm interested in the technique how to use callbacks with arguments without using global variables or putting everything inside main.
There are two main scenarios:
Callbacks with parameters that the caller (popArr() in your example) is expected to choose itself, and
Callbacks with parameters that the callback provider (main() in your example) is expected to specify.
Those are not mutually exclusive. Case (1) has no special requirements -- the caller just passes whatever argument is appropriate, at its own discretion. Case (2) isn't much harder, in principle: the code that provides the callback simply needs to provide the appropriate argument with it. For your very simple case, where the argument and callback do not need to be stored, that would look something like this:
void popArr(int *arr, size_t length, int (*callback)(int *), int *counter) {
// The name of the parameter to (*callback)() is omitted for clarity. It is
// optional in this context.
for (size_t i = 0; i < length; i++) {
arr[i] = callback(counter); // Note: passing counter, not *counter
printf("arr[%zu] is: %d\n", i, arr[i]);
}
}
/* A simple generator callback saving counter. */
int generator(int *counter) {
*counter += 1;
return *counter * 5;
}
/* Main function. */
int main(void) {
int counter = 1;
int arr[10];
// It is unnecessary, but not harmful, to use the & operator on the function
// name. I think it's better style to omit it.
// It is necessary to use the & operator on 'counter', but mainly because
// you want to pass a pointer to counter, as opposed to its value
popArr(arr, 10, generator, &counter);
return 0;
}
I am writing a code in C. It is in an environment with precoded functions, so I can't explain it completely. I wanted to iterate over a variable but this wasn't working. I eventually figured out this was because the variable was not defined globally but in a function, and was being redefined every time the function was called.
Now, at the top of my code, globally, I want to write the following code.
int killing_time = 20000;
int killing_period;
killing_period = killing_time;
The compiler gives me the following errors:
data definition has no type or storage class
Don't I clearly define it to be an integer?
initializer element is not constant
If I define killing_time as const int killing_time = 20000 it still gives the same error:
type defaults to ‘int’ in declaration of ‘killing_period'
I could of course define killing_period to be 20000 and just start iterating over that, but I want to know what is going on.
I hope we can figure this out together.
killing_period = killing_time; is not a valid statement in the global scope.
You can use assignment on declaration, but assigned variable (initializer element) must be constant:
const int killing_time = 20000;
int killing_period = killing_time;
Anyway, you shouldn't do it like that.
There's more than one way to do this, one of them is to pass the address of your iterator to the function where you use it, that way the changes made in the scope of the function are permanent:
void f1(int* i){
(*i)++; //will increment i
}
void f2(int* i){
(*i)++; //will increment i
}
int main ()
{
int i = 0;
f1(&i); //pass the address of i
f2(&i); //pass the address of i
printf("%d", i); // i = 2
return 0;
}
killing_period = killing_time; is executable code and you simply can't have executable code outside functions.
Nor can you do this:
int killing_time = 20000;
int killing_period = killing_time; // wrong
Because these are file scope variables and therefore have static storage duration. And variables with static storage duration can only be initialized by what C calls a constant expression. 20000 above is an integer constant expression, but killing_time isn't.
The simple fix is to do something like this instead:
#define KILLING_TIME 20000
...
int killing_time = KILLING_TIME;
int killing_period = KILLING_TIME;
killing_period = killing_time; is your problem. It is an executable statement and not allowed in global space... it must be within a function.
Still not sure what you are after, but would the following help?
int killing_time = 20000;
int killing_period = -1; // negative if not yet set
int your_function(void)
{
if ( killing_period < 0 ) {
/* one-time initialization on the first call */
killing_period = killing_time;
}
return killing_period;
}
If you need multiple functions setting killing_period it may be be best to burry that in a separate function dedicated to the test and set, or perhaps a macro.
#include <stdio.h>
int main()
{
int i;
for ( i=0; i<5; i++ )
{
int i = 10;
printf ( "%d", i );
i++;
}
return 0;
}
In this variable i is declared outside the for loop and it is again declared and initialized inside for loop. How does C allows multiple declarations?
The i outside the loop and the i inside the loop are two different variables.
The outer i will live for the entire duration of main.
The inner i will only live for the duration of one loop iteration.
The inner one shadows the outer one in this scope:
{
int i = 10;
printf ( "%d", i );
i++;
}
Due to shadowing rules, it is impossible to refer to the outer one while inside the aforementioned scope.
Note that it is impossible to declare two variables with the same name in the same scope:
{
int i = 0;
int i = 1; // compile-time error
}
Variables in one scope can mask variables at a higher scope.
In this example, the i defined inside of the loop masks the i defined outside. In the loop body, the printf prints the value of the inner i, which is 10. The i++ then operates again on the inner i setting it to 11.
When the loop hits the bottom and goes back up, the inner i goes out of scope. The second and third clauses of the for then operate on the outer i. When the loop body is entered again, a new instance of the inner i is defined and initialized to 10.
You should check out the following page for the definitions of the different type of scopes that variables can have in the C language.
http://aelinik.free.fr/c/ch14.htm
Your first int i is in the scope of the entire block, and your second int i only has scope from within that nested loop. Once outside the nested loop, the original block scope version of i is applicable again.
#include <stdio.h>
#include <conio.h>
void main()
{
int i = 1;
{
int i = 2;
printf("%d", i);
}
scanf("%d", &i);
}
I have two local variables with same name. Both have different values. The above program prints 2.
How can I access i with the value with one?
Just make a little change in your code,use integer pointer.As below:
#include <stdio.h>
#include <conio.h>
void main()
{
int i = 1;
int *p = &i; //Address of i given to p(integer pointer)
{
int i = 2;
printf("%d", i);
printf("---->Desire value in inner loop i= %d<-----\n",*p);
}
printf("---->Desire value outside of loop i= %d and *p= %d<-----\n",i,*p);
scanf("%d", &i);
}
In above code integer pointer p having address of i.So whenever u want to access inside inner loop also you can get value of i using integer pointer. Simple is that !!
C follows lexical scope. It means the name resolution of a variable is done depending on the location of the variable in the source code. The variable is resolved by searching its containing block, if that fails then searching the outer containing block.So,
{
int i=2;
printf("%d",i); //this i is the one you defined just above, inside {}
}
This next i would update the i you declared in main()
scanf("%d",&i);
which is this one,
void main()
{
int i=1;
...
So, inside the inner block {}, you cannot access the outer i, since they have the same name, and during the name resolution, the inner i will be found(as first the inner block will be searched for i).
One way is to use pointers, as pointed out by this answer below.
This all about the lexical scope here -
int i = 1;
{ // inside this you can't access the outer i as they have same name so it will be shadowed by inner one
int i = 2;
printf("%d", i); // this will print the value of inner i
}
Similarly you can't access inner i outside these { } .
If you want to print outer i you can just put a printf after the above block ends or you can make use of a pointer like this -
int i=1;
int *p;
p=&i;
and print it .
You should get acquainted with the notions:
Local variables, scope, and duration
Variables that are declared inside a function or block are local variables. They can be used only by statements that are inside that function or block of code. Local variables are not known to functions outside their own.
I have a function in C that I want to output four different values, so rather than using return in my function I decided have four different variables as arguments to the function that would carry their values out of the function back into my main code. I figured if I defined the variables in main and fed them to my other function, they would have whatever value the function gave them after exiting the function. This does not happen though. The variables end up having a value of 0 or close to 0 (like, around 10^-310).
Do I have to declare my variables in a different way/with a different scope to allow them to keep the values they had in a function after exiting the function? Or is there a way to return multiple values in a function?
Here's an excerpt of the relative code:
void PeakShift_FWHM_Finder(double fwhml,double fwhmr,double peak, double max)
{
...//stuff happens to these variables
}
int main()
{
double fwhml,fwhmr,peak,max;
...//other stuff to other variables
PeakShift_FWHM_Finder(fwhml,fwhmr,peak,max)
//These four variables have the right values inside the function
//but once they leave the function they do not keep those values.
...//code continues...
return 0;
}
Use pointers instead.
void PeakShift_FWHM_Finder(double *fwhml,double *fwhmr,double *peak, double *max)
{
...//stuff happens to these variables
// REMEMBER TO DEAL WITH (*var_name) INSTEAD OF var_name!
}
int main()
{
double fwhml,fwhmr,peak,max;
...//other stuff to other variables
PeakShift_FWHM_Finder(&fwhml,&fwhmr,&peak,&max)
//These four variables have the right values inside the function
//but once they leave the function they do not keep those values.
...//code continues...
return 0;
}
What you are looking for is something called Passing by reference
To achieve that, you need to change your declaration to take pointers to the variables. For example
void foo(int * x) {
(*x)++;
}
Then, you can simply invoke that function passing values to it through their address.
int main() {
int i = 10;
foo(&i);
printf("%d", i);
}
What this does is passes the address location of the variable to be modified and the function directly modifies the variable at that address.