C++: The Basics - eps1.10_ExpressionsAndStatements
Hello and welcome. In this blog post we’re going to look at….
“Halt Stop! One more data type and I’ll shut down! #yawn The last few posts have all been about typing variables and constants in C++. We have extensively dealt with primitive data types, user defined data types, arrays of a data type and first data type classes from the standard library. Slowly, there should be enough.”
So or so I fear your thoughts. And indeed, it is enough for the time being. This is a very good selection, with which we are able to solve many problems. After all, the use of variables and constants is only useful if the computer can do calculations with them. And that’s exactly why this time we’ll look at how we can work with them for this purpose.
The art of expression
A calculation or mathematical operation is called expression in technical jargon. It consists of operands and operators. Operands are values to which an operation is applied. Operators are symbols for the operations to be performed. Finally, an expression is a combination of one or more operands with operators.
After the expression is evaluated, the result takes its place. Thus, the simplest case of an expression is a single variable, constant, or literal.
For illustration you find a few examples in listing1.
a = 7
7 - 4
b = 12 + a
// listing1: expressions
b = 12 + a
is a compound expression. The literal 12
and the variable a
are operands. The operator +
combines the two integer data types to a resulting value, which in turn is assigned to the variable b
. Consequently, the value of the entire expression corresponds to the value of b
.
Sounds confusing, but it does not have to be.
Operators must match their respective operands. Remember our definition of a datatype? A datatype consists of a set of values and operations that can be applied to those values. It makes a huge difference if I take the root of d
when d
is of datatype Character or a hexadecimal number.
What if…?
With a conditional expression you can make a case distinction. Suppose you want to determine the larger of two variables for further use. To do this, you only have to formulate the condition as an expression and connect it via the conditional operator ?
with the two cases true and false.
c = (a > b) ? a : b
// listing2: conditional expression
In listing2, the variable c
is assigned the larger of the two values a
and b
. If the question “Is a greater than b” is answered true, then c
is assigned the value of a
. If a
is less than b
the answer to the question is false and b
is assigned.
Here is the syntactic structure of a conditional expression:
Value = Requested condition ? Return value for TRUE : Return value for FALSE
Statement
If you direct an expression as a request for action to the computing unit, you give an instruction (English statement). Basically, every computer program is a sequence of statements. You specify what is to be processed and in what order. To do this, you formulate an expression that is understandable to the CPU and package it in a statement.
What does this mean practically?
In listing3 you see exemplary instructions. You will probably recognize them from previous contributions.
#include <iostream>
int main()
{
int a; // declaration statement
a = 13 + 7; // expression statement
std::cout << a << std::endl; // expression statement
return 0;
}
// listing3: statement
All instructions in C++ end with a semicolon ;
. This defines the boundary between two consecutive statements. Here you can make an analogy to the written language. The semicolon is comparable to the dot .
at the end of a sentence.
You could write your source code in a continuous text with justification. But nobody does that. For a better readability of the source code for the programmer it has been established to write the statements below each other. One line per statement.
The compiler does not care whether the statements are all on one line or distributed over several lines. It ignores blanks, tabs or carriage returns (e.g. std::endl
). But this does not apply to strings
. There every character counts. Everything between the ""
quotes belongs to the string
.
There are even conflicts if the string
is not terminated within a line or separated with a backslash \
.
#include <iostream>
int main()
{
std::cout << "Hello
World" << std::endl; // error
std::cout << "Hello \
World" << std::endl; // valid
std::cout << "Hello "
"World" << std::endl; // valid
return 0;
}
// listing4: strings over two lines
For very long strings
it may be useful for you to split them over several lines for better readability.
Types of instructions
To maintain its reputation as a very complex programming language, C++ distinguishes several types of statements. There are for example:
- Declaration statement
- expression statement / expresssion statement
- loop statement
- selection statement
- compound statement (block)
declaration statement
With the declaration statement you introduce names into your program and make them known to the compiler. The different entities, such as functions, templates, or variables, are all declared in their own way.
So far, we have often declared variables. After this statement, the object, its name and data type are known in the program and only then can you use it.
int main()
{
int anInt; // declaration statement
return 0;
}
// listing5: declaration statement
Expression instruction
We have just looked at what an expression is. If you now want to instruct the computer to execute an expression, then you give it an expression instruction. This sounds more complicated than it actually is. You simply have to follow your expression with a semicolon ;
. Now you have an expression instruction.
After evaluation, an expression stands for a certain value. The expression statement, on the other hand, is usually associated with an action.
To make this a little clearer. Take the expression anInt = 3
. After its evaluation, the expression stands for the value 3
. Only the statement anInt = 3;
lets write the value of the integer literal 3
into the memory of the variable anInt
. The assignment operator =
assigns the value to the variable.
The output to the screen with std::cout
is also an expression. The value in this case is the stream. If you put a simicolon behind it, you give the instruction to output the value to the screen. With the insert operator <<
you can add values to the stream before output.
#include <iostream>
int main()
{
int anInt; // declaration statement
anInt = 3; // expression statement
std::cout << a << std::endl; // expression statement
return 0; // expression statement
}
// listing6: expression statement
The assignment operator =
At the beginning we talked about the components of an expression: operand and operator. Operands can be values from a wide variety of data types. The operator must match the operator set of the data type.
An operator that is very common and that we have already used in an intuitive way is the assignment operator =
. The assignment is a special expression statement. With this operator you replace the value of the operand to its left with the value of the operand to its right.
int main()
{
int anInt;
anInt = 3; // assignment
return 0;
}
// listing7: assignment
An assignment therefore consists of the three parts left operand, operator and right operand. The operands on the left of the operator have the not very creative designation l-value. The operands on the right side are accordingly called r-value.
l-values usually refer to a location in memory. The variable anInt
in listing7 denotes a memory location and is an l-value. The r-value on the other hand stands for the content at a memory location.
The assignment from listing7 can therefore be read: The value of the literal is copied to the memory address after the name anInt
. anInt
and 3
then have the same value.
You can use all l-values also as r-values. However, this does not always work the other way around. You can use the l-value anInt
from our example as r-value and assign its value to another variable. But not to the literal 3
. A literal is similar to a constant not changeable during program runtime. Therefore you cannot copy the value of anInt
to this address.
Initialization or assignment
assignment, declaration, initialization… slowly it becomes confusing. It’s easy to confuse the terms. But for good communication with other developers, a consensus on the meaning of the terms is essential.
So, what’s the difference between an initialization and an assignment?
Making an object known with the declaration is a prerequisite to being able to use the object. So that you can finally use it, you must give it a value beforehand. With the initialization you assign an initial value to an object when you create it.
To express an initialization, C++ offers you several notations. With the assignment operator =
you can initialize variables like in the C programming language. But the more universal form is with an initialization list delimited by curly braces {}
.
If you are not sure why you should use which form for initialization, then decide for the notation with the curly braces {}
. This has the advantage of preventing the loss of information from unwanted type conversions. For compatibility with C, the notation with the assignment operator is valid C++. Unfortunately, this introduces implicit conversion and the risk of losing information.
You can prevent errors during runtime by not leaving any variable uninitialized. The compiler rarely complains about uninitialized variables, because only the memory space is enclosed in the declaration. The data inside consists of any values without initialization. Constants even have to be initialized, because there you have no chance to assign a value during runtime.
So before creating a new variable think about its value.
#include <vector>
int main()
{
int i1; // declaration
i1 = 7; // assigning
double d1 = 1.5; // c-stlye initializing
double d2 {1.5}; // initializing with initializer list
std::vector<int> v1 {1,2,3,4,5,6}; // initializing with initializer list
int i2 = 7.8; // i2 implicitly converts to 7
int i3 {7.8}; // error
return 0;
}
// Listing8: initialising and assigning
Now we have talked so much about initialization. How is it different from an assignment? If you look at the c-style initialization with =
you can hardly see any differences. The basic rule is: An assignment always refers to an already existing object.
For listing8 this means that after the declaration of int i1;
the variable is assigned the value i1 = 7;
. The situation is different for the variable d1
. The double variable is initialized with a value, double d1 = 1.5
.
There is still something missing
After we have taken a closer look at the declaration statement and the expression statement, we are still missing a few already mentioned.
You can recognize the loop statement by the keywords for, while and do .. while. Selection statements start with the keywords if and switch. And a compound statement, also called a block, contains a sequence of statements between its curly braces {}
. The sequence can be empty, host other compound statements. The block represents the compound statement and thus allows to control the flow of a program.
We will deal with these statements and the program flow another time. For this we need first still further operators apart from the assignment operator =
.
That sticks
Once again, we’ve learned a few things. We now know that in an expression operads are connected with operators and thus represent a new value. If you want to have such an operation executed by the computer, you have to pass the expression to it as an instruction. A statement in C++ always ends with a semicolon ;
.
Statements can be subdivided in several ways. We have looked at the declaration and expression statement as well as the assignment. The assignment consists of l-value, assignment operator =
and r-value.
In addition, we can now distinguish the assignment from the initialization.
With the other statement types we can control the program flow. But we cannot start with it yet. We are missing the necessary operators. We will take care of them next time.
I wish you maximum success!
Sources
- [1] B. Stroustrup, A Tour of C++. Pearson Education, 2. Auflage, 29. Juni 2018.
- [2] B. Stroustrup, Programming: Principles and Practice Using C++. Addison Wesley, 2. Auflage, 15. Mai 2014.
- [3] U. Breymann, Der C++ Programmierer. C++ lernen – professionell anwenden – Lösungen nutzen. Aktuell zu C++17. München: Carl Hanser Verlag GmbH & Co. KG; 5. Auflage, 6. November 2017