Discussion:
Scope of variables question
(too old to reply)
x***@y.com
2015-10-17 17:00:19 UTC
Permalink
What is the preferable way to declare a variable in a method?
In other words variables should be declared only in the scope
where they are used?

A)
private void MyMethod()
{
MyType var = new MyType();

if (something)
{
// use var for something
}
else
{
// use var for somrthing else
}
}

B)
private void MyMethod()
{
if (something)
{
MyType var = new MyType();
// use var for something
}
else
{
MyType var = new MyType();
// use var for somrthing else
}
}
Luuk
2015-10-17 18:18:17 UTC
Permalink
Post by x***@y.com
What is the preferable way to declare a variable in a method?
In other words variables should be declared only in the scope
where they are used?
A)
private void MyMethod()
{
MyType var = new MyType();
if (something)
{
// use var for something
}
else
{
// use var for somrthing else
}
}
B)
private void MyMethod()
{
if (something)
{
MyType var = new MyType();
// use var for something
}
else
{
MyType var = new MyType();
// use var for somrthing else
}
}
If you do not use 'var' after the if-else statement, you could use B
If 'var' is used after the if-else statement you cannot use B
x***@y.com
2015-10-17 20:20:33 UTC
Permalink
Post by Luuk
Post by x***@y.com
What is the preferable way to declare a variable in a method?
In other words variables should be declared only in the scope
where they are used?
A)
private void MyMethod()
{
MyType var = new MyType();
if (something)
{
// use var for something
}
else
{
// use var for somrthing else
}
}
B)
private void MyMethod()
{
if (something)
{
MyType var = new MyType();
// use var for something
}
else
{
MyType var = new MyType();
// use var for somrthing else
}
}
If you do not use 'var' after the if-else statement, you could use B
If 'var' is used after the if-else statement you cannot use B
Understood. The variable var is not used after if-else.
The above examples are very simplified.
Both A and B could be used.
But which one should be?
Which one is "better"? "Better" being subject to interpretation.

I have seen some people declare all variables at the beginning of the
procedure.

Is it just a matter of personal style, or is there more to it?
J. Moreno
2015-10-17 20:50:38 UTC
Permalink
Post by x***@y.com
Post by x***@y.com
What is the preferable way to declare a variable in a method?
In other words variables should be declared only in the scope
where they are used?
-snip examples of declarations before if/else and within if/else-
Post by x***@y.com
I have seen some people declare all variables at the beginning of the
procedure.
Is it just a matter of personal style, or is there more to it?
It's not just a matter of style, it's a matter of readability. The shorter
the method, the less it matters, the longer the method the more important
it is to declare as close to the initial usage as possible. Also, does the
variable conceptually capture the same type of information or is it just
coincidentally the same? For instance if you have a person class, and the
variable is spouse, then reusing that for your divorce lawyer is probably
going to be wrong.

In your example, it looks a lot like you are setting the value within the
if/else and then using it after those blocks are done -- in which case you
should declare the variable above. If each is used just within their
respective blocks, then declare them there, so that others know that is the
only place you are going to be using them.
--
J. Moreno
Arne Vajhøj
2015-10-18 02:19:51 UTC
Permalink
Post by x***@y.com
Post by Luuk
Post by x***@y.com
What is the preferable way to declare a variable in a method?
In other words variables should be declared only in the scope
where they are used?
A)
private void MyMethod()
{
MyType var = new MyType();
if (something)
{
// use var for something
}
else
{
// use var for somrthing else
}
}
B)
private void MyMethod()
{
if (something)
{
MyType var = new MyType();
// use var for something
}
else
{
MyType var = new MyType();
// use var for somrthing else
}
}
If you do not use 'var' after the if-else statement, you could use B
If 'var' is used after the if-else statement you cannot use B
Understood. The variable var is not used after if-else.
The above examples are very simplified.
Both A and B could be used.
But which one should be?
Which one is "better"? "Better" being subject to interpretation.
I have seen some people declare all variables at the beginning of the
procedure.
Is it just a matter of personal style, or is there more to it?
#B is better.

But I don't like the example, because I think it is
mixing two issues.

Variables should be declared when needed. So:

if(...)
{
X o = ...;
// using o
}
// not using o

is better than:

X o;
if(...)
{
o = ...;
// using o
}
// not using o

Variables should not be reused for different things. So:

X o1 = ...;
// use o1
X o2 = ...;
// use o2

is better than:

X o = ...;
// use o
o = ...;
// use o

Arne
Jake Bluford
2015-10-18 03:39:57 UTC
Permalink
Post by Arne Vajhøj
Post by x***@y.com
Post by Luuk
Post by x***@y.com
What is the preferable way to declare a variable in a method?
In other words variables should be declared only in the scope
where they are used?
A)
private void MyMethod()
{
MyType var = new MyType();
if (something)
{
// use var for something
}
else
{
// use var for somrthing else
}
}
B)
private void MyMethod()
{
if (something)
{
MyType var = new MyType();
// use var for something
}
else
{
MyType var = new MyType();
// use var for somrthing else
}
}
If you do not use 'var' after the if-else statement, you could use B
If 'var' is used after the if-else statement you cannot use B
Understood. The variable var is not used after if-else.
The above examples are very simplified.
Both A and B could be used.
But which one should be?
Which one is "better"? "Better" being subject to interpretation.
I have seen some people declare all variables at the beginning of the
procedure.
Is it just a matter of personal style, or is there more to it?
#B is better.
But I don't like the example, because I think it is
mixing two issues.
if(...)
{
X o = ...;
// using o
}
// not using o
X o;
if(...)
{
o = ...;
// using o
}
// not using o
X o1 = ...;
// use o1
X o2 = ...;
// use o2
X o = ...;
// use o
o = ...;
// use o
Arne
I think matters were confused when the wording "use var for somrthing
else" was put in the example.

If we changed that to something like this:

private void DetermineWeatherCondition()
{
if (FREEZING_WEATHER)
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = TOO_COLD_FOR_ME;
}
else
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = COMFORTABLE;
}
}

Would you still prefer to see the temperature variable declared in
both spots (i.e. used for the same thing, just different condition)?
Arne Vajhøj
2015-10-18 13:37:33 UTC
Permalink
Post by Jake Bluford
Post by Arne Vajhøj
#B is better.
But I don't like the example, because I think it is
mixing two issues.
if(...)
{
X o = ...;
// using o
}
// not using o
X o;
if(...)
{
o = ...;
// using o
}
// not using o
X o1 = ...;
// use o1
X o2 = ...;
// use o2
X o = ...;
// use o
o = ...;
// use o
I think matters were confused when the wording "use var for somrthing
else" was put in the example.
private void DetermineWeatherCondition()
{
if (FREEZING_WEATHER)
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = TOO_COLD_FOR_ME;
}
else
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = COMFORTABLE;
}
}
Would you still prefer to see the temperature variable declared in
both spots (i.e. used for the same thing, just different condition)?
Yes.

Because it is not really the same. Just same type. There are
some difference in semantics otherwise there would not be
two code blocks.

Arne
Jake Bluford
2015-10-18 15:17:37 UTC
Permalink
Post by Arne Vajhøj
Post by Jake Bluford
Post by Arne Vajhøj
#B is better.
But I don't like the example, because I think it is
mixing two issues.
if(...)
{
X o = ...;
// using o
}
// not using o
X o;
if(...)
{
o = ...;
// using o
}
// not using o
X o1 = ...;
// use o1
X o2 = ...;
// use o2
X o = ...;
// use o
o = ...;
// use o
I think matters were confused when the wording "use var for somrthing
else" was put in the example.
private void DetermineWeatherCondition()
{
if (FREEZING_WEATHER)
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = TOO_COLD_FOR_ME;
}
else
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = COMFORTABLE;
}
}
Would you still prefer to see the temperature variable declared in
both spots (i.e. used for the same thing, just different condition)?
Yes.
Because it is not really the same. Just same type. There are
some difference in semantics otherwise there would not be
two code blocks.
Then my example is not doing a good job of illustrating my point. The
example I wanted to show is a variable for the same purpose simply
receiving a different value.

It's odd that this is considered two code blocks. 30 years ago we
would have just called it "two conditions".

It could be expressed suiccintly like this:

var temperature = SubjectiveCelsiusMeasurement();
temperature = FREEZING_WEATHER ? TOO_COLD_FOR_ME : COMFORTABLE;

I'd rather my developers write this than two code blocks for same.
Luuk
2015-10-18 15:42:57 UTC
Permalink
Post by Jake Bluford
Post by Jake Bluford
private void DetermineWeatherCondition()
{
if (FREEZING_WEATHER)
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = TOO_COLD_FOR_ME;
}
else
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = COMFORTABLE;
}
}
var temperature = SubjectiveCelsiusMeasurement();
temperature = FREEZING_WEATHER ? TOO_COLD_FOR_ME : COMFORTABLE;
I'd rather my developers write this than two code blocks for same.
But these two pieces of code do different things.....

(or is my C# knowledge really that bad ??)
Jake Bluford
2015-10-18 15:51:17 UTC
Permalink
Post by Luuk
Post by Jake Bluford
Post by Jake Bluford
private void DetermineWeatherCondition()
{
if (FREEZING_WEATHER)
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = TOO_COLD_FOR_ME;
}
else
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = COMFORTABLE;
}
}
var temperature = SubjectiveCelsiusMeasurement();
temperature = FREEZING_WEATHER ? TOO_COLD_FOR_ME : COMFORTABLE;
I'd rather my developers write this than two code blocks for same.
But these two pieces of code do different things.....
(or is my C# knowledge really that bad ??)
I'm not sure, in your original example you may have been describing a
different situation when you said "two different things". If you are
taking a variable and literally using it for completely different
purposes, I would say its a bad idea to use the same variable name for
two different purposes. So yes in that case I think its good to
declare the variable inside each block and give it a name that
describes how its used in each block, rather than redundantly declare
it with the same name. But, because you used a non-realistic name
like MyType it was hard to know your intention.

In my example, the variable is not used for two different purposes,
only to receive two different values.
Arne Vajhøj
2015-10-18 19:37:47 UTC
Permalink
Post by Jake Bluford
Post by Arne Vajhøj
Post by Jake Bluford
Post by Arne Vajhøj
X o1 = ...;
// use o1
X o2 = ...;
// use o2
X o = ...;
// use o
o = ...;
// use o
I think matters were confused when the wording "use var for somrthing
else" was put in the example.
private void DetermineWeatherCondition()
{
if (FREEZING_WEATHER)
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = TOO_COLD_FOR_ME;
}
else
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = COMFORTABLE;
}
}
Would you still prefer to see the temperature variable declared in
both spots (i.e. used for the same thing, just different condition)?
Yes.
Because it is not really the same. Just same type. There are
some difference in semantics otherwise there would not be
two code blocks.
Then my example is not doing a good job of illustrating my point. The
example I wanted to show is a variable for the same purpose simply
receiving a different value.
var temperature = SubjectiveCelsiusMeasurement();
temperature = FREEZING_WEATHER ? TOO_COLD_FOR_ME : COMFORTABLE;
Yes.

But I think it illustrates the point.

No blocks and one variable is fine.

Two blocks and two variables is fine.

Two blocks and one variable indicate either suspicious reuse of
variable or suspicious usage of blocks.
Post by Jake Bluford
It's odd that this is considered two code blocks. 30 years ago we
would have just called it "two conditions".
The block concept in relation to if statements goes back to
ALGOL more than 50 years ago.

Arne
Jake Bluford
2015-10-18 21:39:03 UTC
Permalink
Post by Arne Vajhøj
Post by Jake Bluford
Post by Arne Vajhøj
Post by Jake Bluford
Post by Arne Vajhøj
X o1 = ...;
// use o1
X o2 = ...;
// use o2
X o = ...;
// use o
o = ...;
// use o
I think matters were confused when the wording "use var for somrthing
else" was put in the example.
private void DetermineWeatherCondition()
{
if (FREEZING_WEATHER)
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = TOO_COLD_FOR_ME;
}
else
{
var temperature = new SubjectiveCelsiusMeasurement();
temperature = COMFORTABLE;
}
}
Would you still prefer to see the temperature variable declared in
both spots (i.e. used for the same thing, just different condition)?
Yes.
Because it is not really the same. Just same type. There are
some difference in semantics otherwise there would not be
two code blocks.
Then my example is not doing a good job of illustrating my point. The
example I wanted to show is a variable for the same purpose simply
receiving a different value.
var temperature = SubjectiveCelsiusMeasurement();
temperature = FREEZING_WEATHER ? TOO_COLD_FOR_ME : COMFORTABLE;
Yes.
But I think it illustrates the point.
No blocks and one variable is fine.
Two blocks and two variables is fine.
Two blocks and one variable indicate either suspicious reuse of
variable or suspicious usage of blocks.
I think in such a small method as the example, as long as the variable
is re-used properly, it's not a problem to have it declared once at
the top.

In practice I don't find suspicious usage of blocks to be too big of
an issue, they are usually there as a language convention, either to
group multiple statements or to open and close a method for example.
If I saw the use of naked code blocks of evidence of code blocks that
were there without an obvious purpose, I might start taking a closer
look at the rest of the method to see what's going on.

For example, in a switch statement with 10 different cases, there
could be code blocks in each one. What a mess if it declares the same
variable 10 different times to use it the same way with a different
value. It means now, if that variable is renamed or deleted, the
reader of the method needs to take a look at each case and figure out
what to do. Then again if the method is getting large enough to
declare the same variable 10 times, some questions about whether
multiple methods should have been used would come to light.
Arne Vajhøj
2015-11-28 21:51:31 UTC
Permalink
Post by Jake Bluford
Post by Arne Vajhøj
No blocks and one variable is fine.
Two blocks and two variables is fine.
Two blocks and one variable indicate either suspicious reuse of
variable or suspicious usage of blocks.
I think in such a small method as the example, as long as the variable
is re-used properly, it's not a problem to have it declared once at
the top.
In practice I don't find suspicious usage of blocks to be too big of
an issue, they are usually there as a language convention, either to
group multiple statements or to open and close a method for example.
If I saw the use of naked code blocks of evidence of code blocks that
were there without an obvious purpose, I might start taking a closer
look at the rest of the method to see what's going on.
For example, in a switch statement with 10 different cases, there
could be code blocks in each one. What a mess if it declares the same
variable 10 different times to use it the same way with a different
value.
A case in a switch it not a code block (distinct scope) so you can
not duplicate variable names without extra curly brackets.
Post by Jake Bluford
It means now, if that variable is renamed or deleted, the
reader of the method needs to take a look at each case and figure out
what to do. Then again if the method is getting large enough to
declare the same variable 10 times, some questions about whether
multiple methods should have been used would come to light.
That is something you will always have to do.

The tricky scenario is if you are reusing the variable and some
blocks require a change but other blocks requires changes not to be
done.

Arne
x***@y.com
2015-10-24 07:05:31 UTC
Permalink
Post by Arne Vajhøj
No blocks and one variable is fine.
Two blocks and two variables is fine.
Two blocks and one variable indicate either suspicious reuse of
variable or suspicious usage of blocks.
Can you elaborate on why this is bad or suspicious?

An example:

private void MyMethod(int type)
{
switch (type)
{
case 1:
{
DataTable dt = GetData1();
// do something with dt
}
break;
case 2:
{
DataTable dt = GetData2();
// do something else with dt
}
break;
}
}
GetData1 and GetData2 are two different methods.

The same variable, dt, in two blocks. What is wrong with that?
Jake Bluford
2015-10-24 16:04:42 UTC
Permalink
Post by x***@y.com
Post by Arne Vajhøj
No blocks and one variable is fine.
Two blocks and two variables is fine.
Two blocks and one variable indicate either suspicious reuse of
variable or suspicious usage of blocks.
Can you elaborate on why this is bad or suspicious?
private void MyMethod(int type)
{
switch (type)
{
{
DataTable dt = GetData1();
// do something with dt
}
break;
{
DataTable dt = GetData2();
// do something else with dt
}
break;
}
}
GetData1 and GetData2 are two different methods.
The same variable, dt, in two blocks. What is wrong with that?
My thoughts:

GetData1() and GetData2() are methods that must have different
purposes (if they had the same purpose, they would be the same method
just returning a different value).

This is a bit hard to see with fictitous names like GetData1() or
GetData2(), but let's change the names to:

CelsiusTemperature() and FarenheitTemperature()

...both basically getting the temperature, both returning a numeric
value, but performing very different functions because the value
coming back from them cannot be used interchangably semantically.

So in the interest of readable code, I'd want to see something like:

case 1: // the instrument expects the measurement in celsius
{
var CelsiusReading = CelsiusTemperature();
}
break;
case 2: // the instrument is in farenheit mode
{
var FarenheitReading = FarenheitTemperature()
}


In this case, declaring a single variable at the top would be bad,
because it is used for different purposes in two different code
blocks. But different purposes are not different values.

For example, using a single variable to store a freezing celsius temp
or a boiling celsius temp is an example of storing two different
values, not two different purposes.

It does come down to subjective evaluation sometimes depending on what
the code is actually doing.
Arne Vajhøj
2015-11-28 22:01:08 UTC
Permalink
Post by x***@y.com
Post by Arne Vajhøj
No blocks and one variable is fine.
Two blocks and two variables is fine.
Two blocks and one variable indicate either suspicious reuse of
variable or suspicious usage of blocks.
Can you elaborate on why this is bad or suspicious?
private void MyMethod(int type)
{
switch (type)
{
{
DataTable dt = GetData1();
// do something with dt
}
break;
{
DataTable dt = GetData2();
// do something else with dt
}
break;
}
}
GetData1 and GetData2 are two different methods.
The same variable, dt, in two blocks. What is wrong with that?
Nothing.

As I wrote:

#Two blocks and two variables is fine

To illustrate:

# Two blocks and one variable indicate either suspicious reuse of
# variable or suspicious usage of blocks.

Try rename that variable dt to something more documentative:

switch (type)
{
case 1:
{
DataTable dataForX = GetData1();
// do X with data table
}
break;
case 2:
{
DataTable dataForY = GetData2();
// do Y with data table
}
break;
}

is still fine. But:

DataTable dataForAnything;
switch (type)
{
case 1:
{
dataForAnything = GetData1();
// do X with data table
}
break;
case 2:
{
dataForAnything = GetData2();
// do Y with data table
}
break;
}

shows that you can't name the variable properly because it is used for
two different things.

Of course then we have:

DataTable dataForX;
switch (type)
{
case 1:
{
dataForX = GetData1();
// do X with data table
}
break;
case 2:
{
dataForX = GetData2();
// do X with data table
}
break;
}

but those blocks are not good and it should really be written as:

DataTable dataForX;
switch (type)
{
case 1:
{
dataForX = GetData1();
}
break;
case 2:
{
dataForX = GetData2();
}
break;
}
// do X with data table

Arne
Stefan Ram
2015-12-26 19:13:14 UTC
Permalink
Post by x***@y.com
private void MyMethod()
{
MyType var = new MyType();
if (something)
{
// use var for something
}
else
{
// use var for somrthing else
}
}
One of the most well-known and important rules for sound
software engineering is that the scope of an identifier
should be as small as possible.

For one example why this is good, imagine that you want
to apply a the refactor »extract method«.
Post by x***@y.com
private void MyMethod()
{
if (something)
{
MyType var = new MyType();
// use var for something
}
else
{
MyType var = new MyType();
// use var for somrthing else
}
}
With the code directly above, I just move the block.

private void extracted()
{ MyType var = new MyType();
/* use var for something */ }

private void MyMethod()
{ if( something )extracted();
else
{ MyType var = new MyType();
/* use var for something else */ }}

With the code given at the beginning, this would have been
more difficult.
Luuk
2015-12-26 20:03:27 UTC
Permalink
Post by x***@y.com
What is the preferable way to declare a variable in a method?
Why are you replying on an old thread?
Last post in this thread was from 28-11-2015....
Post by x***@y.com
One of the most well-known and important rules for sound
software engineering is that the scope of an identifier
should be as small as possible.
When googling for 'scope of identifier', i find this article:
https://vineetgupta22.wordpress.com/2011/11/09/scope-of-identifier/

In this article i do not find the word 'small'
--
Below the text of the the article:
Scope of Identifier


In computer programming, scope is an enclosing context where values and
expressions are associated. Various programming languages have various
types of scopes. Typically, scope is used to define the extent of
information hiding – that is, the visibility or accessibility of
variables from different parts of the program. Scopes can:

•contain declarations or definitions of identifiers;
•contain statements and/or expressions which define an executable
algorithm or part thereof;
•nest or be nested.

Scope is a property of the program text and is made independent of the
runtime call stack by the language implementation. Because this matching
only requires analysis of the static program text, this type of scoping
is also called static scoping. Lexical scoping is standard in all
ALGOL-based languages such as Pascal, Modula2 and Ada as well as in
modern functional languages such as ML and Haskell. It is also used in
the C language and its syntactic and semantic relatives, although with
different kinds of limitations. Static scoping allows the programmer to
reason about object references such as parameters, variables, constants,
types, functions, etc. as simple name substitutions. This makes it much
easier to make modular code and reason about it, since the local naming
structure can be understood in isolation. In contrast, dynamic scope
forces the programmer to anticipate all possible dynamic contexts in
which the module’s code may be invoked.

It is important to have a good understanding of scope because if you try
to use an Identifier that’s not in scope, you will get the compiler
error. An Identifier is available only after its definition has ended,
meaning that is not usually possible to define an Identifier in terms of
itself. The portion of the program where an identifier can be used is
known as its scope. For example, when we declare a local variable in a
block, it can be referenced only in that block and in blocks nested
within that block. The type of scope is always determined by the
location of which you declare the Identifier (except for labels which
always have function scope) There are four type of scopes: function,
file, block and function prototype.

1. Block Scope

Objective-C code is divided into sequences of code blocks and files that
define the structure of a program. Each block, referred to as a
statement block, is encapsulated by braces ({}). Each block has its own
scope. No conflict occurs if the same identifier is declared in two
blocks. If one block encloses the other, the declaration in the enclosed
block hides that in the enclosing block until the end of the enclosed
block is reached. We may also state that when the block is exited, the
names declared in the block are no longer available.

When one block is nested inside another, the variables from the outer
block are usually visible in the nested block. However, if the
declaration of a variable in a nested block has the same name as a
variable that is declared in an enclosing block, the declaration in the
nested block hides the variable that was declared in the enclosing
block. The original declaration is restored when program control returns
to the outer block. This is called block visibility. For example:



1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include <stdio.h>
int main(){
int i = 32; /* block scope 1*/
printf("Within the outer block: i=%d\n", i);
{
int i, j; /* block scope 2, int i hides the outer int i*/
printf("Within the inner block:\n");
for (i=0, j=10; i<=10; i++, j--){
printf("i=%2d, j=%2d\n", i, j);
}
} /* the end of the inner block */
printf("Within the outer block: i=%d\n", i);
return 0;
}


Program Output:

Within the outer block: i=32

Within the inner block:

i= 0, j=10

i= 1, j= 9

i= 2, j= 8

i= 3, j= 7

i= 4, j= 6

i= 5, j= 5

i= 6, j= 4

i= 7, j= 3

i= 8, j= 2

i= 9, j= 1

i=10, j= 0

Within the outer block: i=32

2. Function scope

A label is the only kind of identifier that has function scope. A label
is declared implicitly by its use in a statement. Label names must be
unique within a function.

3. File scope

Identifiers appearing outside of any block, function, or function
prototype, have file scope. Identifier names with file scope are often
called “global” or “external.” The scope of a global identifier begins
at the point of its definition or declaration and terminates at the end
of the translation unit. Unlike other scopes, multiple declarations of
the same identifier with file scope can exist in a compilation unit, so
long as the declarations are compatible.

Some coding guidelines documents recommend that the number of objects
declared at file scope be minimized. However, there have been no studies
showing that alternative design/coding techniques would have a more
worthwhile cost/benefit associated with their use. Identifiers declared
as types must appear at file scope if:

•objects declared to have these types appear at file scope,
•objects declared to have these types appear within more than one
function definition (having multiple, textual, declarations of the same
type in different block scopes is likely to increase the cost of
maintenance and C does not support the passing of types as parameters),
•other types, at files scope, reference these types in their own
declaration.

Any program using file scope objects can be written in a form that does
not use file scope objects. This can be achieved either by putting all
statements in the function main, or by passing, what were file scope,
objects as parameters. The following are some of the advantages of
defining objects at file scope (rather than passing the values they
contain via parameters) include:

•Efficiency of execution. Accessing objects at file scope does not incur
any parameter passing overheads. The execution-time efficiency and
storage issues are likely to be a consideration in a freestanding
environment, and unlikely to be an issue in a hosted environment.
•Minimizes the cost of adding new function definitions to existing
source code. If the information needed by the new function is not
available in a visible object, it will have to be passed as an argument.

The function calling the new function now has a requirement to access
this information, to pass it as a parameter. This requirement goes back
through all call chains that go through the newly created function. If
the objects that need to be accessed have file scope, there will be no
need to add any new arguments to function calls and parameters to
existing function definitions.

The following are some of the disadvantages of defining objects at file
scope:

•Storage is used for the duration of program execution.
•There is a single instance of object. Most functions are not recursive,
so separate objects for nested invocations of a function are not usually
necessary.
•Reorganizing a program by moving function definitions into different
translation units requires considering the objects they access. These
may need to be given external linkage.
•Greater visibility of identifiers reduces the developer effort needed
to access them, leading to a greater number of temporary accesses.
•Information flow between functions is implicit. Developers need to make
a greater investment in comprehending which calls cause which objects to
be modified. Experience shows that developers tend to overestimate the
reliability of their knowledge of which functions access which file
scope identifiers.
•When reading the source of a translation unit, it is usually necessary
to remember all of the file scope objects defined within it. Reducing
the number of file scope objects reduces the amount of information that
needs to be in developers long-term memory.

The only checks made on references to file scope objects is that they
are visible and that the necessary type requirements are met. For
issues, such as information flow, objects required to have certain
values at certain points are not checked (such checking is in the realm
of formal checking against specifications). Passing information via
parameters does not guarantee that mistakes will not be made; but the
need to provide arguments acts as a reminder of the information accessed
by a function and the possible consequences of the call.

4. Function prototype

The declarator or type specifier for an identifier with
function-prototype scope appears within the list of parameter
declarations in a function prototype (not part of the function
declaration). Its scope terminates at the end of the function
declarator.For example:

int students ( int david, int susan, int mary, int john );

In this example, the identifiers (david, susan, mary , and john ) have
scope beginning at their declarations and ending at the closing
parenthesis. The type of the function students is “function returning
int with four int parameters.” In effect, these identifiers are merely
placeholders for the actual parameter names to be used after the
function is defined.

INTERNATIONAL STANDARD – Programming languages – C, described the
Scopes of an Identifiers as under:

1. An identifier can denote an object; a function; a tag or a member of
a structure, union, or enumeration; a typedef name; a label name; a
macro name; or a macro parameter. The same identifier can denote
different entities at different points in the program. A member of an
enumeration is called an enumeration constant. Macro names and macro
parameters are not considered further here, because prior to the
semantic phase of program translation any occurrences of macro names in
the source file are replaced by the preprocessing token sequences that
constitute their macro definitions.

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.)

3. A label name is the only kind of identifier that has function scope.
It can be used (in a goto statement) anywhere in the function in which
it appears, and is declared implicitly by its syntactic appearance
(followed by a : and a statement).

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.

5. Unless explicitly stated otherwise, where this International Standard
uses the term ‘‘identifier’’ to refer to some entity (as opposed to the
syntactic construct), it refers to the entity in the relevant name space
whose declaration is visible at the point the identifier occurs.

6. Two identifiers have the same scope if and only if their scopes
terminate at the same point.

7. Structure, union, and enumeration tags have scope that begins just
after the appearance of the tag in a type specifier that declares the
tag. Each enumeration constant has scope that begins just after the
appearance of its defining enumerator in an enumerator list. Any other
identifier has scope that begins just after the completion of its
declarator.

8. As a special case, a type name (which is not a declaration of an
identifier) is considered to have a scope that begins just after the
place within the type name where the omitted identifier would appear
where it not omitted
Arne Vajhøj
2015-12-26 20:39:28 UTC
Permalink
Post by Luuk
Why are you replying on an old thread?
Last post in this thread was from 28-11-2015....
Sometimes people think they can write something worth
reading even if the thread is old.

(but I did not see anything new in this specific
post)
Post by Luuk
Post by Stefan Ram
One of the most well-known and important rules for sound
software engineering is that the scope of an identifier
should be as small as possible.
https://vineetgupta22.wordpress.com/2011/11/09/scope-of-identifier/
In this article i do not find the word 'small'
I am not quite sure that I can see your point.

That something is not mentioned in a blog post on the
internet does not really say anything.

There are plenty of different wordings
with the same meaning: "limit scope", "minimize scope"
etc., so a search on the word 'small' does not show much.

Stefan's claim is commonly known.

If you want an example from the internet:

https://en.wikipedia.org/wiki/Variable_%28computer_science%29

"It is considered good programming practice to make the scope of
variables as narrow as feasible"

Arne

Continue reading on narkive:
Loading...