Lesson 3: Operators, Functions, and Basic Scope
C++ has a lot of operators. A lot. 55, to be exact. But, don't worry, because we will only be covering a handful of the most common ones here. Operators are organized into groups by their precedence level - which ones resolve before others.
// For convenience, operators will be grouped in order by precedence
std::cout; // The operator here is the ::, which is the scope resolution operator. It tells the compiler that you are referencing the cout object in the std namespace. More about namespaces in a later tutorial.
a++; a--; // The ++ and -- are postfix increment and decrement operators. They return the value of a, and then respectively increase and decrease the value of a by 1. If a was 5, a++ would return 5, and then change the value of a to 6.
f(); // The () is the function call operator, which follows the function name.
array[0]; // The [] is the array subscript operator, which returns the given element in the array. In this case, it would return the first element.
++a, --a; // Like the postfix increment and decrement, the prefix operators do the same thing, except they increment/decrement the value of a before returning it. If a was 5, ++a would increase the value of a to 6, and then return 6.
+a; -1; // These operators are called unary plus and minus (unary meaning taking one argument). They are used to change the sign of a number, to positive or negative, respectively.
!true; // The ! operator is called the logical NOT operator - it returns the opposite of the given boolean argument.
~a; // The ~ operator is called the bitwise NOT operator - it returns the given value with all of its bits flipped.
(int) a; // The operator here is actually the type name in parentheses. It causes the given argument to be interpreted as the given data type.
sizeof int; // The sizeof operator returns the size of a given type, class, or data object, in bytes. On most systems, sizeof int would return 4.
5 * 4; 2 / 1; 5 % 2; // The multiplication, division, and modulus operators. They would exactly how you would expect, with a few small caveats. If two different integral/floating-point types are given as arguments, the result is given in the larger of the two types. For this purpose, floating-point types are always considered larger than any integral type. Also, / does integer division if it is given 2 integral arguments: 5 / 2 == 2. If either (or both) of the arguments is a floating-point type, the operator does floating-point division: 5.0 / 2 == 2.5.
2 + 2; 2 - 5; // The addition and subtraction operators work exactly how you would expect.
5 < 2; 2 <= 2; 3 > 1; 3 >= 42; // The comparison operators, which work exactly how you would expect.
5 == 5; 2 != 3; // Equivalence and non-equivalence operators, self-explanatory.
true && true; // Logical AND, returns true if both arguments resolve to true, and false otherwise.
false || true; // Logical OR, returns true if either or both of the arguments resolve to true, and false otherwise.
a = 5; // Direct assignment, exactly what it says on the tin.
a += 2; a -= 3; a *= 3; a /= 2; // These work just like the regular arithmetic operators, and they also assign the return value to the left operand.
a + 5, b + 2; // The comma operator is the lowest-priority operator. The first operation is performed, its return value is discarded, and then the second operation is performed, with its return value returned. This has nothing to do with comma-separated lists, like function arguments.
The next part of the lesson will be about functions. As per usual, I will provide example code first, and then explain how it works.
#include <iostream>
using namespace std;
int addition(int a, int b) {
return a + b;
}
void foo() {
cout << "Foo!" << endl;
}
int main() {
foo();
cout << addition(2, 2) << endl;
return 0;
}
Foo!
4
Let's get down to business, and figure out what the hell I just did.
Functions are pieces of code that can be called by name to execute their code. This is a huge benefit, because functions allow programmers to refer to code with a name, rather than typing the same code over and over.
int addition(int a, int b)
This is a function header. It tells the return type for the function (int), the name (addition), and the types and names of the required arguments (two int's, which are called a and b inside of the function).
{
return a + b;
}
This is the function body, which contains the code for the function. As you can see, the function simply returns the sum of a and b.
void foo()
This is another function header, with a twist - it has a void return type, which means it returns nothing. Ok, I lied, it has two twists - it also has an empty argument list, which means it will not accept any arguments. None. Nada. Zero. Zilch.
...okay, you get the point.
{
cout << "Foo!" << endl;
}
The function body tells us that, when foo is called, "Foo!" will be written to the standard output, followed by a newline.
foo();
This is the syntax for calling a function with no arguments. At this point in the program, "Foo!" and a newline have been written to the standard output.
cout << addition(2, 2) << endl;
Here, we call addition with 2 for both arguments. Our expertise in mathematics tells us that we will get 4 as the return value. That 4 is printed (with a newline) to standard output.
Now, why would I put operators and functions in the same tutorial? Clearly, they're two different things, right?
WRONG! (mostly)
Operators are functions, but with some special syntax. Binary operators go between their operands, instead of the operands going in an argument list following the operator name. Unary operators go either before or after their operand. Also, when using operators, you don't use the function-call operator.
Now for a basic discussion of scope rules.
int foo(int a) {
int b = 2;
return a + b;
}
int main() {
int c = foo(2);
b = 4; // compile error - b does not exist!
return 0;
}
If you tried to compile this, you'd get an error saying that b does not exist. But, clearly, we defined b in the foo function! Well, that only means that b is defined within the scope of that function. As soon as that function returns, b stops existing. A rule of thumb is, any time you see a set of curly braces, a new scope is being introduced.
It's funny how, after typing a word a lot, it stops seeming like a real word. Scope scope scope scope scope.