1

I have a code written in c, basically it takes in an array and prints it backward. A pretty basic thing. Here's the code:

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

int main(){
    int n; 
    scanf("%d",&n);
    int *arr = malloc(sizeof(int) * n);
    for(int arr_i = 0; arr_i < n; arr_i++)
    {
       scanf("%d",&arr[arr_i]);
    }
    for(arr_i=n-1; arr_i >= 0;arr_i--)
    {
      printf("%d ",arr[arr_i]);   
    }
    return 0;
}

I get the following error for the second for loop:

solution.c:17:9: error: ‘arr_i’ undeclared (first use in this function)

  for(arr_i=n-1; arr_i >= 0;arr_i--)

When I insert int before the arr_i in the second for loop the error goes away.

So, my doubt is that why is that even though I have already declared arr_i in first for loop, it asks me to declare it once again in the second for loop?

Community
  • 1
  • 1
  • If you decalra the variable as a separate declaration at the start of the function, it can be used where ever needed. – sabbahillel Jan 05 '17 at 18:57

4 Answers4

7

The scope of arr_i is limited to only the first for loop. In the second loop, is does not live.

Quoting C11, chapter §6.2.1

[...] If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. [...]

To elaborate, one of the available sytax for for loop is

 for ( declaration expressionopt ; expressionopt ) statement

which is used in your case. As the declaration of arr_i appears in the clause-1 of the for loop, the scope is limited to the loop scope and thus, this identifier is undeclared outside the loop.

If you want that same variable to be used in both the loops, define the variable in the block scope for the whole function, in this case, the main() function.

That said, a general advice, always check for the success of malloc() before using the returned pointer.

Note: As you mentioned,

When I insert int before the "arr_i" in the second for loop it goes away.

it's worth mentioning that, in that case, there are two different variables existing in two different scope. They are not the same variable.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • when calling any of the heap memory allocation functions (malloc, calloc, realloc) always check (!=NULL) the returned value to assure the operation was successful. – user3629249 Jan 06 '17 at 08:54
  • when calling any of the `scanf()` family of functions, always check the returned value (not the parameter value) to assure the operation was successful. – user3629249 Jan 06 '17 at 08:56
  • in general, when expecting input from the user, prompt the user, telling them what they are expected to input. – user3629249 Jan 06 '17 at 08:58
  • Whats the point? Very simple. The OP seems to be a beginning programmer. And lots of formal class room teaching fails to cover the need to check for errors. And also does not discuss why the code needs to check for errors. (in the current scenario, if an error occurs, then the code will be writing to small offsets from address 0. This is undefined behavior and can (usually will) result in a seg fault event. So the code should check for the error and if the error occurs, then report the error (to stderr) via calling: `perror()` then `exit( EXIT_FAILURE );` – user3629249 Jan 06 '17 at 09:07
  • @user3629249 that was my reply to your very first comment and that was already mentioned in the answer. – Sourav Ghosh Jan 06 '17 at 10:11
1

As Sourav Ghosh already pointed out, when you declare a variable in a for (this case), that variable only exists in that loop. Example:

void test ()
{
    int normal_variable = 5;
    {
        int local_variable = 10;//only exists here
        printf("It compiles: %d and work.\n", local_variable);
        printf("It also works: %d",normal_variable);
    }
    printf("Doesn't compile because doesn't exists: %d.",local_variable);
    printf("It also works, because it already exists: %d",normal_variable);
}

The brackets are the ones that make this possible. If you wanna read more about it, check this:

Where you can and cannot declare new variables in C?

Community
  • 1
  • 1
Kxp
  • 13
  • 1
  • 6
1

Well thats actually one nice feature of a for loop compared to a while loop, The variable only lives as long as the For block structure and you can declare it inside the for block parameters. So just declare it outside the structure(before) and you will be find, learn more about scopes and variable lifetimes.

int main(){
int n; 
scanf("%d",&n);
int *arr = malloc(sizeof(int) * n);
int arr_i = 0; 
for( ; arr_i < n; arr_i++)
{
   scanf("%d",&arr[arr_i]);
}
//
for(arr_i=n-1; arr_i >= 0;arr_i--)
{
  printf("%d ",arr[arr_i]);   
}
return 0;

}

Also looking over your code n is not given any value, you can address it but it has no value(Its actually an undetermined value), malloc( sizeof(int) * n ) will be 4bytes * (undetermined).. so set it to 0 if anything. I'm not sure if this is some pseudo code but this is covered with errors, I'd write it for you but since you are beginning you should do it yourself :) practice makes perfect. Saying that comment if you need more help.

Zach Hutchins
  • 801
  • 1
  • 12
  • 16
  • 1
    If you are going to use the single variable, I would much prefer to see the initialization in the loop control rather than in the variable definition. Generally, it is good to initialize when you define, but IMO it is even Morris important to have all control information for a `for` loop in the loop control line. – Jonathan Leffler Jan 05 '17 at 19:26
1

the scope of a variable is what counts.

The first declaration, in the first loop, has a scope of that loop

So it is not visible in the second loop.

user3629249
  • 16,402
  • 1
  • 16
  • 17