How do global and static variables work together in C? - c

I have to determine the output of this program (without running it on the computer). I am pretty unsure on how the global and static variables work together.
#include <stdio.h>
void f(int d);
int a = 1, b = 2, c = 3, d = 4;
int main()
{
int a = 5, c = 6;
f(a);
f(b);
f(c);
printf("%d %d %d %d\n",a,b,c,d);
return 0;
}
void f(int d)
{
static int a = 0;
a = a + 7;
b = a + d;
c++;
d--;
printf("%d %d %d %d\n",a,b,c,d);
}

Local variable defintions always "hide" global variables with the same name. An inner scope always takes precedence over an outer one. Some compilers also produce warning when a variable "shadows" another one.

The nearest visible binding in scope hides all the further ones. So in main all the names refer to the local variables, and in f only a is the local one (albeit static, that's immaterial), d refers to the function parameter, and b and c refer to the global ones.
You can unhide farther-away names to a limited extend with the extern keyword, but given enough local scopes you can always create and hide variables that you can never see from somewhere deeper.

If two variables are declared with the same identifier, the accesses refer to the one with the smallest scope.
C11 (n1570), § 6.2.1 Scopes of identifiers
If an identifier designates two different entities in the same name
space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end
strictly before the scope of the other entity (the outer scope). Within the inner scope, the
identifier designates the entity declared in the inner scope; the entity declared in the outer
scope is hidden (and not visible) within the inner scope.

Related

C: what is the name space of a type definition?

What name space is a typedef name in? Consider this code:
#include <stdio.h>
typedef struct x { // 'x' in tag name space
int x; // 'x' in member name space
int y;
} x; // ??
int main() {
x foo = { 1, 2 };
int x = 3; // 'x' in ordinary identifier name space
printf("%d %d %d\n", foo.x, foo.y, x);
}
This prints out '1 2 3' with gcc 4.4.7 (and g++ 4.4.7), so type names are separate from tag, member, and ordinary identifier names.
This code also compiles and runs on gcc/g++ 4.4.7, producing '1, 2':
#include <stdio.h>
typedef struct x { // 'x' in tag namespace
int x; // 'x' in member namespace
int y;
} x;
int main() {
x x = { 1, 2 };
printf("%d %d\n", x.x, x.y);
}
How are the x identifiers disambiguated in this case?
EDIT
A clarification, I hope. Consider these two lines from above:
x foo = { 1, 2 };
int x = 3; // 'x' in ordinary identifier name space
When the second line is executed, identifier x is in scope, and should logically be in the 'ordinary identifier' namespace. There doesn't appear to be a new scope at this point, because there is no opening brace between lines 1 and 2. So the second x can't hide the first x, and the second x is in error. What's the flaw in this argument, and how does this apply to the x x case? My assumption was that the flaw was that type names somehow had a different non-obvious name space, hence the title of this question.
It works not due to namespaces (the new type name and the variable identifier are in the same ordinary namespace), but due to scoping.
6.2.1 Scopes of identifiers
2 For each different entity that an identifier designates, the
identifier is visible (i.e., can be used) only within a region of
program text called its scope. Different entities designated by the
same identifier either have different scopes, or are in different name
spaces. There are four kinds of scopes: function, file, block, and
function prototype. (A function prototype is a declaration of a
function that declares the types of its parameters.)
4 Every other identifier has scope determined by the placement of
its declaration (in a declarator or type specifier). If the declarator
or type specifier that declares the identifier appears outside of any
block or list of parameters, the identifier has file scope, which
terminates at the end of the translation unit. 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. If the declarator or type specifier that declares
the identifier appears within the list of parameter declarations in a
function prototype (not part of a function definition), the identifier
has function prototype scope, which terminates at the end of the
function declarator. If an identifier designates two different
entities in the same name space, the scopes might overlap. If so, the
scope of one entity (the inner scope) will end strictly before the
scope of the other entity (the outer scope). Within the inner scope,
the identifier designates the entity declared in the inner scope; the
entity declared in the outer scope is hidden (and not visible) within
the inner scope.
The variable named x is an an inner scope. So it hides the entity named x in the outer scope. Inside the scope of main, following the declaration of x x, it's a variable name.
The interesting bit is that in x x = { 1, 2 }; the meaning of x is changed mid declaration. In the beginning it denotes the type name, but once the declarator introduces an identifier, x starts denoting the variable.
Regarding your edit "What's the flaw in this argument?" Note that scopes may overlap (as the preceding paragraph mentions). The definition of the type alias is actually at file scope. The block scope of main is a new inner scope that overlaps the outer scope. That's why it can be used to hide the previous meaning of x. Had you tried to do this at file scope:
typedef struct x { /* ... */ } x;
int x = 1; // immediately at file scope
It would be ill-formed. Because now indeed the declarations appear at the exact same scope.

Namespace scope in c confusion

Reading a lot of definition of namespace and scopes cannot understand exactly the difference between the two terms.
For example:
If an identifier designates two different entities in the same name
space, the scopes might overlap.
It is really confusing me. Can someone clarify it as simple as possible underlining the difference.
You left off the second part of that statement:
If so, the scope of one entity (the inner scope) will end
strictly before the scope of the other entity (the outer scope). Within the inner scope, the
identifier designates the entity declared in the inner scope; the entity declared in the outer
scope is hidden (and not visible) within the inner scope.
Online draft of the C2011 standard, §6.2.1, para 4.
Example:
void foo( void )
{
int x = 42;
printf( "x = %d\n", x ); // will print 42
do
{
double x = 3.14;
printf( "x = %f\n", x ); // will print 3.14
} while ( 0 );
printf( "x = %d\n", x ); // will print 42 again
}
You have used the same identifier x to refer to two different objects in the same namespace1. The scope of the outer x overlaps the scope of the inner x. The scope of the inner x ends strictly before the scope of the outer x.
The inner x "shadows" or "hides" the outer x.
C defines four namespaces - label names (disambiguated by the `goto` keyword and `:`), struct/union/enum tag names (disambiguated by the `struct`, `union`, and `enum` keywords), struct and union member names (disambiguated by the `.` and `->` operators), and everything else (variable names, function names, typedef names enumeration constants, etc.).
"Namespace" in C has to do with the kinds of things that are named. Section 6.2.3 of the standard distinguishes four kinds of namespaces
one for labels
one each for the tags of structures, unions, and enumerations
one for the members of each structure or union
one for all other identifiers
Thus, for example, a structure tag never collides with a variable name or the name of any structure member:
struct foo {
int foo;
};
struct foo foo;
The usage of the same identifier, foo, for each of the entities it designates therein is permitted and usable because structure tags, structure members, and ordinary variable names all belong to different name spaces. The language supports this by disambiguating the uses of identifiers via language syntax.
"Scope", on the other hand, has to do with where -- in terms of the program source -- a given identifier is usable, and what entity it designates at that point. As section 6.2.1 of the standard puts it:
For each different entity that an identifier designates, the identifier is visible (i.e., can be used) only within a region of program text called its scope. Different entities designated by the same identifier either have different scopes, or are in different name spaces.
Identifiers belonging to the same namespace may have overlapping scope (subject to other requirements). The quotation in your question is an excerpt from paragraph 4 of section 6.2.1; it might help you to read it in context. As an example, however, consider
int bar;
void baz() {
int bar;
// ...
}
The bar outside the function has file scope, starting immediately after its declaration and continuing to the end of the enclosing translation unit. The one inside the function designates a separate, local variable; it has block scope, starting at the end of its declaration and ending at the closing brace of the innermost enclosing block. Within that block, the identifier bar designates the local variable, not the file-scoped one; the file-scoped bar is not directly accessible there.

Scope of a variable and function name

This is my code:
#include <stdlib.h>
#include <stdio.h>
int sum(int,int);
int sum(int x, int size) {
int sum = 0;
printf("%p\n", &x);
printf("%p\n", &size);
printf("%p\n", &sum);
sum(x,size);
return 0;
}
int main() {
sum(2,4);
return 0;
}
And the error I am getting is:
hello.c:11:5: error: called object type 'int' is not a function or function pointer
sum(x,size);
~~~^
You changed the meaning of sum here:
int sum = 0;
From now on, in the scope in which it was declared, sum is an int, and this becomes nonsense:
sum(x,size); /* Wat? sum is an int!!! */
Don't do that, and your code will compile. Once it compiles, you can worry about stopping the recursion.
If you define two separate identifiers of same name for different entities in the same name space, they might overlap. C11 standard, chapter §6.2.1 states,
If an identifier designates two different entities in the same name
space, the scopes might overlap....
Refer Footnote: Why in this scenario, both sums are in same name space
So, once you re-define the identifier with some other type,
....If so, the scope of one entity (the inner scope) will end
strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
That means, essentially, in your case, inside function sum(), when you're defining int sum, basically you're shadowing the function sum. After the re-definition, sum is an identifier of type int, in that function scope. Thus, inside the function sum(), you cannot make a call to sum() as that is an int type now.
However, FWIW, the call to sum() in main() (or, rather, outside sum() itself) should be valid, as at that point, int sum will be out of scope.
Solution: Change the int sum variable name to something else.
Thanks to #pmg for the correction
EDIT:
As mentioned in the other answer by #juanchopanza, after changing the shadowing variable name, your program will compile and once you run it, you'll face infinite recursion due to the unconditional call to sum() inside sum() itself. You need to add some break condition to end (return from) the recursion.
FootNote:
Referring to C11, chapter §6.2.3, name spaces, we can say, there are separate name spaces for various categories of identifiers, e.g. 1) label names 2) the tags of structures, unions, and enumerations, 3) the members of structures or unions and 4) all other identifiers.
So, in this particular case, the function sum() and the int sum definition will reside in the same name space, for the sum() function scope
The scope matters
Function name sum here has a global scope.
Variable sum is local and has local scope.
The conflict is because inside sum() you call sum(). Now inside function sum() you have 2 objects of same name and of different type hence the error.
If you had something like
int sum()
{
int sum = 0;
sum = 10;
printf("%d\n",sum);
}
Then your code would have been fine. Since variable sum is local to function sum() and it is the only object within function sum() with that name.
Instead of worrying about this better to rename the variable and make sure variable name and function name is different
You need to change int sum = 0 to int y = 0, also your program will break as you dont stop recursion at sum(x,sum)
Simply change variable sum name inside sum function to total
#include <stdlib.h>
#include <stdio.h>
int sum(int,int);
int sum(int x, int size) {
int total = 0;
printf("%p\n", &x);
printf("%p\n", &size);
printf("%p\n", &total);
sum(x,size);
return 0;
}
int main() {
sum(2,4);
return 0;
}
Variable and function is of same name thats why it is de-referencing function and variable same time thats the cause of error

Why doesn't declaring a variable with the same name outside and inside a loop produce an error?

{
int i;
for(i=0;i<5;i++)
{
int i=10;
printf("%d",i);
}
}
I have two questions
Why is there no redeclaration error for i?
why output will be 10 5 times and not 10 1 time?
It all has to do with the scope of an identifier. An identifier is simply a name given to an entity (object, function, typedef name and so on) in C and, as per C11 6.2.1 /1:
The same identifier can denote different entities at different points in the program.
The scope of an entity is described in /2 of that section:
For each different entity that an identifier designates, the identifier is visible (i.e., can be used) only within a region of program text called its scope.
And /4 covers your specific case:
If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope).
In other words, something like:
{
int i = 42;
printf ("%d ", i);
{
int i = 17;
printf ("%d ", i);
}
printf ("%d\n", i);
}
is perfectly valid, and will print 42 17 42. That's because the identifier i inside the inner block is in its own scope, which ends at the first closing brace.
In your particular case, you can think of it as:
{
int i; \
for(i=0;i<5;i++) > outer i scope
{ /
int i=10; \
printf("%d",i); > inner i scope
} /
}
The inner int i=10 effective hides the outer i for the duration of the body of the for loop. That's why it prints a lot of 10s rather than 0..4.
The scope of the inner i finishes at the closing brace of the for loop body so that, when the continuation condition of the for loop is checked, it once again sees the outer i. That's why it loops five times rather than once.
In your code
int i; is in outer block scope.
int i=10; is in the inner block scope for the for loop
If we visualize the same, we can come up with something like'
{ //---------------------------|
int i; |
for(i=0;i<5;i++) |
{ |
int i=10; //-------| inner scope |> Outer scope
printf("%d",i); //-------| |
} |
} //----------------------------|
The case here is, the inner i will shadow the outer i. These two are considered seperate variable (based on their scope).
In other words, the i which is defined and present inside the block (inner scope) will have more preference (over the variable in outer scope). So, the inner i value will get printed.
OTOH, the loop counter variable i remains at the outer scope. It's value is not altered through the assignement inside the block. So, rightly it loops for 5 times, as asked.
Related: From C11 standard, chapter §6.2.1, paragraph 4,
..[..].. If an identifier designates two different entities in the same name
space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
So, to answer your questions,
Why is there no redeclaration error for i?
Because two is are treated as seperate variable, despite being named same.
why output will be 10 5 times and not 10 1 time?
Because, the outer i, used as the counter, is not changed from inside the loop, only the loop increment condition is altering that value.
You aren't re-declaring i since the second declaration of i ( 'int i =10' ) is inside a loop . That's means that in your example the variable is destroyed and recreated for each iteration of the loop .
The scope of variables created in any compound statement is limited to the compound statement itself .
Ps : If you wanted to stop the loop by changing the value of i
{
int i;
for(i=0;i<5;i++)
{
i=10;
printf("%d",i);
}
}
If you ask your compiler nicely (gcc -Wshadow) it will warn you
echo -e '#include <stdio.h>\nvoid f(void) { int i; for (i = 0; i < 5; i++) { int i = 10; printf("%d", i); } }' | gcc -Wshadow -xc -c -
<stdin>: In function 'f':
<stdin>:2:53: warning: declaration of 'i' shadows a previous local [-Wshadow]
<stdin>:2:20: note: shadowed declaration is here

Terminology definition - Scope in C application

Is there a specific term for the following type of C code? In my example, I want to increase the depth of scope for a small chunk of code within a function without having to use needless if/else/for statements so that I can re-declare a variable with the same name multiple times. eg:
void myfunc(void) {
int a = 0, b = 1;
{
int c;
c = 3;
printf("c is: %d", c);
}
a = 2;
{
int c = 5;
printf("c is %d", c);
}
}
What is the term used to describe how I just wrapped some code in curly braces and increased the scope depth so the rest of the function doesn't see the 'c' int?
Thanks!
Scope is defined as the area in which the object is active. There are five scopes in C. They are as follows.
Program Scope
These are the declarations at the top most layers. They are available up to the life of a program. All the functions have this scope. This is otherwise known as global scope.
File Scope
It has scope such that it may be accessed from that point to the end of the file.
void dummy(void) { }
// absence of static automatically gives program scope to `dummy()`
static void dummy(void) { }
// static keyword here gives function `dummy()` a file scope
Function Scope
Only labels have this scope. In this scope, they are active up to end of the function.
void printFun()
{
print:
printf(“i is less than j”);
}
int main()
{
int i=1,j=2;
if(i < j)
goto print;
}
This code will be flagged error by the compiler saying that the label print is not known because labels have only function scope. If you have to jump unconditionally between the functions, you have to use setjmp/longjmp functions.
Block Scope
Declarations that are active up to the end of the block (where a block is defined as statements within { }). All the declarations inside the function have only block scope.
int fun(int a, int b)
{
int c;
{
int d;
}
// a, b, c, d all have block scope
}
As I have said, function scope applies only to labels. So should not be confused with block scope. The function arguments are treated as if they were declared at the beginning of the block with other variables (remember that the function body is also considered as a block within { }). So the function arguments have block scope (not function scope).
Local scope is general usage to refer the scope that is either function or block scope.
Prototype Scope
They are having the scope only inside the prototype declaration. This scope is interesting because the variable names are valid only in the declaration of prototype and does not conflict with other variable names. It exists for very little time and of less use and so goes unnoticed.
int add(int a, float b);
Here the variables a and b are said to have prototype scope.
Selecting Minimal Scope
When a name has to be resolved, that name is searched in the minimal scope, and if that is not available, it is searched at higher levels of scope. So, if a variable has to be declared, you have to select a minimal scope possible. If you can limit your scope, that increases the efficiency, readability and maintainability of your program. If you want a variable which is not useful outside a block, declare it inside the block and not in the outer ones. Similarly, if you want a variable whose value will be accessed only within the function but has to retain the value between the function calls, opt for static variable to a global one.
I'd say you are introducing a new local scope, or a nested scope, or a block.
This becomes seriously important in C++ when you take active advantage of this:
{
std::lock_guard<std::mutex> lk(my_mutex);
do_critical_stuff(); // might throw exception?
}
// the lock is released automagically!
But even in C it's good practice to only use variables locally where they're needed and not bleed them into unnecessarily wide scopes.
The term is the scope.
K&R2 defines the word scope as
A name also has a scope, which is the region of the program in which
it is known
Scope is the word that refers to the visibility of an identifier.

Resources