This paper covers the history and use of labels in programming languages, from the beginning of programming to the present day. In early programming languages, labels were used a lot and had to be in specified positions. In present day languages can be most any place and are not used as much to branch to, but are used with loops and switch statements. The rules for using and constructing labels still vary a lot among present languages.
Copyright Dennie Van Tassel 2004.
Please send suggestions and comments to dvantassel@gavilan.edu
Labels
are used to branch to using goto statements
in C and wide variety of other languages.�In Java
labels�are used to exit (break) a named loop, or skip (continue)�iterations of a named loop. In BASIC and
FORTRAN labels are used to indicate the boundaries of a block of code to be
executed. The term labels is mostly universal across languages, except in
COBOL, their labels are called paragraph names. COBOL uses paragraph names�(labels) as a place to branch to
using a goto
statement, and paragraph names are used to group statements into blocks of code
to be executed by PERFORM ( similar
to a for loop) commands. The
case-selector in switch statements is very similar
to a label and used to branch to in some languages (C#).
Labels�started as positive integers
(i.e., goto 20) in early BASIC and FORTRAN or alphanumeric
identifiers with rules for composition similar to variables in later languages.
Both COBOL and C++ could use:
�� goto errors
for
a branch, but C++ programmers would not admit to such use.
Here
are a few design issues�for labels:
All
of the answers to these questions are yes in some language. We will now cover
some of these label design issues in this chapter.
Here
is a list of labels�composition in several languages.
|
Language |
Label Syntax |
|
BASIC |
100 |
|
QBasic,
Visual Basic |
start_here: |
|
FORTRAN
IV |
100 |
|
FORTRAN
90 |
starthere: |
|
ALGOL |
100:� or� start_here: |
|
|
<<start_here>> |
|
COBOL |
START-HERE.� or
100-START-HERE. |
|
Java/C++/C |
start_here: |
Sample Labels
by Language
Many
languages use colons�at the end of the label. COBOL uses a period
to terminate their paragraph (label) names. One other oddity about COBOL
paragraph names is that they can start with a digit (10-START).
The
infamous goto statement is used to do an
unconditional branch�to a label. In our wild programming youth we
used to do many of those, but with age we have reformed and do very few. Some
languages such as FORTRAN and COBOL use the two word version go to, while other languages such
as the C family use the single word version goto. But FORTRAN ignores
spaces, so either version could be used. in FORTRAN.
There
is some question where a label can be placed in a line. Labels�are often placed at the
beginning of a line. Besides making it easier to find a label by someone
reading the program, there are historical reasons for this placement. Early
languages (BASIC, FORTRAN, and COBOL) were line
(card) oriented and very concerned with positions or columns on the line
(card). Early FORTRAN and BASIC use positive integers at the beginning of the
line. These labels�cannot be elsewhere in the line. See examples
below in this section. In modern languages labels can be even after a statement
but are seldom used in this way. Here is where labels and statements must be in
three early languages.
|
Column # |
1-5 |
6 |
7-72 |
73-80 |
|
|
Labels |
Continuation
indicator |
Program
statements |
Sequence
or program name |
FORTRAN Statement Layout
Figure x.1
BASIC
labels are also integers that must be placed at the beginning of all the lines.
The rest of the line was used for commands.
COBOL used alphanumeric paragraph names (labels), which had to start within positions (columns) 8-11, but could and usually continued after position 11. A COBOL label ends with a period. COBOL�statements start in position 12 or later, so it easy to distinguish labels from other items in a COBOL program. Thus in all three of these early languages the position of the label in the line was closely restricted.
|
Column # |
1-6 |
7 |
8-11 |
12-72 |
73-80 |
|
|
Sequence |
Continue |
Labels
must start here |
Program
statements |
Program
name |
COBOL Statement Layout
Figure x.2
Early
versions of these three languages (FORTRAN, BASIC, COBOL) are fixed source form�� meaning that statements must
be in specific positions.
In
FORTRAN, COBOL, and BASIC the sequence positions were used to sequence number
the program statements. Programs were written on cards and after you dropped
your cards on the floor because you were so excited to get an answer to 4 place
accuracy, you needed some way to put the cards back in order.
In
modern languages we should be able to do the following:
�� A = 0;��
mylabel:�
b = 2;
In
this code snippet we have the label mylabel: between two statements on the same line. Not all
languages will allow this rather odd code. For example, in VB .NET, labels must
appear at the beginning of a line of source code (following its BASIC heritage)
, so the above code would be incorrect.
Labels
can go any place in a program in most languages. But some early languages
require that only certain type of statements must follow. For example, in
FORTRAN statements are divided into executable and non-executable statements.
Executable statements specify some action to take during execution of the
program. Examples of executable
statements�are assignment statements,
branches, loops, and calculations, all which do something. Non-executable statements�provide information to the
compiler. Examples of non-executable statements are declaring arrays or types
of variables. FORTRAN�declarations such as the type statements INTEGER and REAL cannot have labels. Likewise, array declarations, DATA statements, and the END statement cannot have a
label. This last restriction appears in other languages. For example, we cannot
have the following FORTRAN code:
������ goto 190
������ . . .
������ print
*, "All done."
�190�� end
In this code the integer 190 is a FORTRAN label. Instead we would need to change it to something like this:
������ goto 190
������ . . .
�190�� print *, "All done."
������ end
FORTRAN IV needs an executable statement after a label and end is not an executable statement. Later versions of FORTRAN allow branches to end statements.
Other languages have similar requirements. For example, C needs a statement after a label. Here is an example, in the C family:
������ goto done;
������ . . .
� done: ;�
/* null statement here. */
������ }
In
this snippet of code we use a null statement�after the label done, since a statement must follow labels.
A
related restriction is whether two or more labels�can be used next to each other.
For example, can we have something similar to the following:
� error1: error2:� cout << "input or output error" << endl;
In
this interesting code snippet we have two consecutive labels�error1 and error2. Some languages object to
this.
Dead
code�are variables that are declared
but never used, functions that are never called, or code that is skipped
because of a branch. Since the dead code is not executed, it is an error, often
a logic error. Dead code is created by careless programmers. An easy way to
create dead code is by use of a goto statement and labels. Here is an example:
�� goto processing;
�� a = a + 1;�
// dead code here.
Since
we have an unconditional branch to the label processing on the first line, the assignment statement on the second line can
never be executed. A return statement can be used to
make dead code in Java and most other languages. Here is an example:
�� return;
�� x = x = 1;�
// dead code here.
We
can create dead code a little more subtly in COBOL as follows:
��� IF
RATE IS GREATER THAN MINIMUM THEN
������ GO
TO UNDER-RATES
��� ELSE
GO TO OVER-RATES.
��� IF
RATE IS EQUAL TO MINIMUM THEN
������ GO
TO MATCHED-RATES.
So
let�s see how awake you are! Look at the above code again. Are we going to
three different places depending on whether RATE is less than, equal, or
greater than MINIMUM? Actually, the second IF statement is another
example of dead code. The program either branches to UNDER-RATES or OVER-RATES in the first IF statement, but never gets to the EQUAL test
statement!
FORTRAN
programmers only put labels�on lines needed for reference. The
FORTRAN DO loop is similar to the for loop in modern languages.
Here is a FORTRAN example:
������ DO
10, K = 1, 10, 1
��������� PRINT
*, K, 1.0/K
The "DO 10 . . ." indicates the start of the loop and the "10 CONTINUE" indicates the end of the loop. I have taken a few liberties with the early FORTRAN syntax of the PRINT command to make it readable for you. FORTRAN IV labels�must be in the first 5 positions of the line, and any place within those columns. The labels must be unsigned integers and 5 or fewer digits. The rest of the FORTRAN statements must be in positions or columns 7-72. Labels did not have to be in any order but FORTRAN programmers usually tried to use small numbers near the beginning of the program and large numbers near the end of the program. Thus when looking for the label 10 we would expect (hope) it was near the beginning of the program and label 4200 was near the end of the program, or a long way from the beginning.
FORTRAN used statement labels�to indicate the end of DO loops, as above, but also a line to branch to as follows:
������ DO 10, K=1, 11, 1
��������� M = K - 6
��������� IF (M .EQ. 0) GOTO 10
��������� PRINT *, M, 1.0/M
�10��� CONTINUE
Two uses of labels�are illustrated. The number 10 is used to indicate the last line of the DO loop, and the label is used as place to branch to with a goto statement. The above code will not print the inverse of zero, since that is a difficult inverse to calculate.
Early
BASIC numbered all the lines, often by 10s so lines could be inserted later. So
here is the same code in BASIC:
��� 210 FOR
K = 1 TO 11 STEP 1
��� 220���
M = K � 6
��� 230��� IF
(M = 0) THEN GOTO 250
��� 240��� PRINT
M, 1.0/M
��� 250 NEXT K
���
All
lines were numbered and the lines were sequence checked by the BASIC
interpreter. Thus in BASIC the line numbers had two purposes: 1) used for
labels; 2) used to keep program in order. Later versions of BASIC added
alphanumeric labels, which are covered later
in this section.
A
few languages allow us to assign values to a label�similar to how a variable�is assigned a value. This
programming flexibility means when reading a program we cannot tell where the
program is branching. Here is how a few languages handle this.
We
can use a label variable to modify the destination of the goto�statement.
Here is a FORTRAN�example using an assigned goto�statement:
�� assign
10 to dest
�� . . .
�� if
(hours .gt.
40.0) assign 20 to dest
�� . . .
�� goto dest
Thus
the program will branch to either label 10 or 20, depending on the value of label variable dest. The obvious problem here
is that when we are reading the program, it is difficult to figure out the
value of dest. But then on the other
hand, we do this with regular variables all the time. So it is curious that
label variables are so strongly condemned but other variables are accepted.
If
you have a strong desire to do something like this in another language that has
pointers, you might be able to use pointers to point to a function, and modify
the function pointed to. Don�t tell your teacher I even suggested this is
possible!
Both
FORTRAN and Perl have a computed goto, which works similar to a switch statement. It is covered in
the Switch chapter.
Most
the labels�discussed so far have used label�constants. A label constant is a
label that cannot change in value, just like a numeric constant cannot change
in value. For example:
�� 123.45���
// numeric constant.
� start:����
// label constant.
We
could use the numeric constant in an assignment statement (x = 123.55;) and we can use the label
constant in a branch (goto start).
Labels
do not often have to be declared. Pascal requires labels to be declared, but
the label is a constant and can not be modified or passed as a parameter.
Labels are declared similar to standard variable declarations. Here is an
example:
� �label errors, 120;
��� . . .
�� goto errors;
��� . . .
�� errors:
We
have declared two Pascal labels and code snippet branches to the label errors. Labels can be standard identifiers or
unsigned integers. But with integer labels, leading zeros are not significant
in labels, so "0012" and "12" are the same label. Declaring
labels is seldom used in programming languages and may have been found to have
little use.
In PL/I�we can declare a label�variable as follows:
�� DECLARE
LBL LABEL INITIAL (ERRORS);
Now we can place a label value in LBL and use that label any place it is needed. In this example, the label variable LBL is initialized with the label value ERRORS. So "GOTO LBL" statement actually branches to the label ERRORS.
After
we set up the label variable LBL, we can assign a label
constant to it. For example:
�� LBL = START;
Now we can use LBL as follows:
�� GOTO
LBL;
and
the branch will go to where label START is located.
Label
variables�are rare in computer languages and commonly
condemned by programming gurus. Besides the common damning of label variables,
the actual fact seems to be that label variables are not very useful. These
PL/I label variables can also be used as parameters in functions or
subroutines. For example, we can use the above label variable LBL as follows:
�� x = zap(2, LBL, cost);
In this line, function zap, uses integer constant 2, then label variable LBL, and variable cost. So we can pass a label variable or numeric variable to a function.
Since we can have label�variables, it is not a large jump to have arrays of labels. Since this is interesting but may not be the most needed topic, I will cover it briefly. Here are two different label arrays declarations:
�� DECLARE L(4) LABEL;
�� DECLARE LABS(4) LABEL
����� INITIAL(START,
PROCESS, ERROR, ENDING);
The first label array can be used with subscripts:
�� L(I): X = . . ./*
�� GOTO L(K);�
In both cases the subscript identifies the label. For example if K = 2, then label L(K) is L(2). PL/I arrays start at one, not zero.
The second DECLARE statement above, initialized the label array. In this case, if LABS(1) is used, that references label START. If LABS(2) is used, that references label PROCESS. Here is more of the example:
�� START: . . .
�� . . .
�� PROCESS: . . .
�� . . .
����� GOTO LABS(K);
While all this is kind of intellectually interesting (at least to me), it did not seem to have been used much. You will need to find an old PL/I manuals to read about this topic, since many newer manuals seldom even discuss it.
We now move on to the early COBOL ALTER�verb that probably deserves the award�for the worst programming language command. At least in the above FORTRAN and Pl/I use of variable labels, we were modifying a label variable and had some warning it may be modified. COBOL has the ALTER verb that allows us to modify a label�constant. This was early on condemned and is difficult to even find in COBOL�textbooks, but is still there for your use in most versions of COBOL. These undesirable commands are kept in the language to keep it upward compatible. Here is an example:
�� PROCESSING.
����� PERFORM PROCESS-HEADING.
����� ALTER PROCESS-HEADING TO PROCESS-RECORDS.
In this code we alter the meaning of the label constant PROCESS-HEADING to point to the paragraph name (label) PROCESS-RECORDS. This could be done any place in the program and done more than once, so we have no hint on where the program is actually branching too. Much to the credit of COBOL programmers, this command was easily condemned and seldom used. The PERFORM verb is used to execute a loop, but the same problem surfaces with go to statements:
�� GO TO PROCESS-HEADING.
Now the go to may branch to the PROCESS-HEADING paragraph if it has not been changed to really mean PROCESS-RECORDS. Since the ALTER verb could be part of an IF statement, exactly what is happening could be difficult to determine.
ALGOL
was one of first languages to introduce blocks (using begin ... end), which then allowed global
and local variables. The ALGOL labels�also gained global and local
variables. Previously, in languages like FORTRAN II and IV all statement labels
were global to the subroutine that used the label. Now we have scope of labels
too in ALGOL. We can have duplicated labels in different blocks and it is
impossible to transfer into the middle of another block.
Most
early languages (FORTRAN, COBOL, and BASIC) the scope of the label is the whole
program. It had to be this way since these early languages did not have a block
structure. In Pascal variables have normal scope, but labels also have the same
scope. Pascal allows us to include functions and procedures within the main
program. The labels in these nested functions also have local scope.
C
and C++ labels�do not have scope. Labels can be inside or
outside blocks, above or below and the scope of the label is the whole program.
The only label scope is within in functions.
Labels�can have their own namespace. That is, since terminating the label with a colon indicates labels, we can also have variables with the same name as a label, even though
it may confuse us. Java does not allow variables and labels to be the same. But
other languages do allow it, but textbooks and documentation are often vague
about the rules.
In
C++ we can use a label with the same name as a function, such as sqrt, but cannot
use reserved words for labels. Thus we could have something similar to:
����� goto sqrt;
�� . . .
�� sqrt: . . .
Now
some of you may wonder why we would want to do this, but we are just trying to
get a better understanding of labels.
In
C++ we can also have a label and variable with the same name. Thus we can have
something similar to:
�� int xyz=5;
�� . . .
�� goto xyz;
�� . . .
xyz: . . .
In
this code we have a variable xyz and a label xyz. This is not allowed in Java. The Java inventors
were previous C programmers and probably wanted to clean up this confusion.
Many
other languages allow variables and labels�to be the same word. Examples
are QBasic, COBOL, C, C#, and VB (??check last two).
This
section covered the construction and syntax of labels�in several languages. Besides
what was covered here the actual use of the label is covered with the commands
that use the labels elsewhere in the book. In the section on loops, look at
"Labeled Loops," for ways to branch to a label without using the 4-letter word
that starts with "g" which has fallen into such disfavor, that some authors
proud themselves by writing a whole book on programming without mentioning g*?o..�Probably the extreme exile is in Java, where goto is a
reserved word, but not used as command. Thus we cannot use goto as a command or a variable name in Java. But one
time I snuck a goto into a Java program by
doing it this way goto_s. In C# and a few other
languages you can use a goto to branch to a
case-selector label and this is covered in the Switch chapter.
1.
Using what you have learned in this chapter how would you design
statement labels? There are several
interesting questions, such as placement, character set, terminator, scope,
differentiate from variables, etc. Indicate the rules for labels in your design
of OPL.[1]
2.
Labels could have scope (similar to how variables have scope) when the
language has a block structure. Do we want labels�to have scope? Indicate the
rules for label scope in your design of OPL. Do we need global and local
labels?
3.
Pick a couple languages you are familiar with and see if a label can be
a reserved word, keyword, or function name. See if you can determine this from
a textbook or language documentation. After you think you know the answers to
those questions verify them by writing some small programs.
4.
Pick a language you are not familiar with and try to find the answers
in some documentation for that language for the previous two questions.
4.
Some languages have allowed variables to hold labels, and to allow functions to be passed labels. How could we do this for
our OPL and would we want to? Can you come up with an example, where it would
be useful to pass a label to a function? One language that does this is PL/I.
5.
Labels have changed as older languages have been updated. Trace how
labels�have changed in a language like
BASIC or FORTRAN, both of which have gone through many versions.
6.
The namespace of labels�is also a little complicated and
often not well documented. For example, can we have a label and variable with
the same name? What about having a label in an outer block and available with
the same name in inner block? Try this in both Java and C++ (or two other
languages) and see what happens.
7.
The goto controversy waged hot and
heavy in the late 1960s and early 1970s. Too good places to start reading about
it are the article by E. W. Dijkstra, "Goto Statement Considered Harmful."[2]
which started the discussion, and a later reply to this controversy by D. E.
Knuth, "Structured Programming with GOTO Statements."[3]
Look up these two articles and write a paper about the controversy and your
opinion of the results.
8.
Some languages require a statement after a label. For example, the
program can not have a label immediately before an ending block. Here is an
example:
���������� out_x:�� }
This can be fixed by placing a null statement after the label out_x and before the closing brace.
Look at a few languages and see if this is a problem in those languages. A
related restriction is that two labels�may not be next to each other.
See if this is true in some languages you are familiar with.
ALTER
COBOL................................................................... 9
angle brackets
Ada labels............................................................. 2
assigned goto......................................................... 6
award
worst command.................................................... 9
BASIC
labels...................................................................... 6
branch
unconditional........................................................ 2
break
labels...................................................................... 1
COBOL
ALTER verb.......................................................... 9
labels...................................................................... 3
colon
label use................................................................. 2
continue
labels...................................................................... 1
dead code.................................................................. 5
design issues
labels...................................................................... 1
Dijkstra..................................................................... 12
executable statements.............................................. 4
fixed source form...................................................... 3
FORTRAN
assigned goto....................................................... 6
labels.................................................................. 3,
4
g*?o.......................................................................... 11
goto
assigned................................................................ 6
Java...................................................................... 11
labels...................................................................... 1
vs go to.................................................................. 2
inverse of zero........................................................... 6
Knuth....................................................................... 12
labels.................. 1,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
arrays..................................................................... 8
constant................................................................. 9
constants............................................................... 7
design issues........................................................ 1
FORTRAN............................................................. 4
integers.................................................................. 1
namespace........................................................... 10
placement.............................................................. 3
variables............................................................ 6,
8
namespace
labels.................................................................... 10
non-executable statements..................................... 4
null statement
branch point.......................................................... 4
paragraph names
COBOL................................................................... 1
PL/I
label variables....................................................... 8
unconditional branch............................................... 2
variables
label.................................................................... 6,
8
This file is from www.gavilan.edu/csis/dvantassel/languages/labels.html
Date last revised
Copyright Dennie Van Tassel, 2004.
Send comments or suggestions to dvantassel@gavilan.edu
I am especially interested in errors or omissions and I have
other chapters on History of Programming Languages.
[1]� Our Programming Language (OPL) is a programming language we are designing using the material covered in this book.
[2] E. W. Dijkstra, "Goto Statement Considered Harmful." Communications of the ACM, Volume 11, No. 3, 1968.
[3] D. E. Knuth, "Structured Programming with GOTO Statements," ACM Computing Surveys, Volume 6, No. 4, 1974.