Question

Suppose we have something along these lines

int f(int n);

....

do{
    int a = b;
    int b = f(a);
}

Is there any risk to saying

do{
    int b = f(b);
}

instead, assuming a is not used elsewhere? Would it be stylistically preferable to do the former?

Was it helpful?

Solution

It is important to understand that you're not "altering" any variables here, just changing the meaning of a name.

The important concept is called the point of declaration.

Let's look at your example:

int b = 42;
{ 
   int a = b; 
   int b = 23 * a;
   printf("%d\n", b);
}
printf("%d\n", b); 

or

int b = 42;
{ 
   int b = 23 * b;
   printf("%d\n", b);
}
printf("%d\n", b); 

The name b references two objects, depending on where you are in the code, let's call them b1 and b2. This is unsurprising in case 1:

int b1 = 42;
{ 
   int a = b1; 
   int b2 = 23 * a;
   printf("%d\n", b2);
} 
printf("%d\n", b1); 

Since in C the point of declaration is before the initializer, the second example resolves differently:

int b1 = 42;
{ 
   int b2 = 23 * b2; 
   printf("%d\n", b2);
} 
printf("%d\n", b1); 

Note that here there's no link between b1 and b2, you're initializing b2 with its own (undefined) value. A diligent compiler will warn you about this, like

x.c:7:13: warning: 'b' is used uninitialized in this function [-Wuninitialized]

OTHER TIPS

As the compiler parses C code it populates a symbol table, this table contains information about all the different symbols and by symbols I mean identifiers, such as the names you give your variables, functions, and so forth ...

Most C programs are constructed out of nested scopes, global -> function -> component_statements and so on, each scope usually has its own symbol table, so the compiler uses a stack of symbol tables to keep track of everything, when a variable is looked up but isn't defined in the current symbol table it starts the search by going upward the stack until it hits global or usually last table ... but as soon one is defined in the current scope an entry is made 'shadowing' the previous.

heres a simple program to illustrate.

#include <stdio.h> 
/* global accessable by most things ... */
int a = 5;
int main()
{ /* function scope */
    int a = 4; /* shadowing global */
    { /* nested scope within function scope */
        int b = a;
        int a = b; /* shadowing function  */
        printf("%i\n", a);
    }
    return 0;
 }

if you run this you would get 4 which is to be expected but anyone following your code would have to keep in the back of their mind that a is different from all the other a from global, function main ... If the programmer maintaining the code isn't aware of this things or you yourself forgot then you can have subtle run-time bugs that can be quite hard to debug ...

also note that if you run this:

#include <stdio.h> 
/* global accessable by most things ... */
int a = 5;
int main()
{ /* function scope */
    int a = 4; /* shadowing global */
    { /* nested scope within function scope */            
        int a = a; /* shadowing function, but not actually accessing outer scope */
        printf("%i\n", a);
    }
    return 0;
 }

you wouldn't get 4 but some large random int on my machine its 1606422610 since the variable is being assigned to itself that was just shadow, and c doesn't initialize variables.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top