This is an old revision of the document!
Operators represent mathematical, relational, bitwise, conditional, or logical data manipulations. There are many operators in the C/C++ language. In this chapter, the most important are presented. Logical operators will be shown in the next chapter as they are used together with conditional statements.
Arithmetic operations are used to do mathematical calculations with numbers or numerical variables. The arithmetic operators are the following.
int result = 1 + 2; //The result of the addition operation will be 3
int result = 3 - 2; //The result of the subtraction operation will be 1
int result = 2 * 3; //The result of the multiplication operation will be 6
//The result of the division operation will be 3 //(Only the whole part of the division result) int result = 7 / 2; //The result of the division operation will be 3.5 float result2 = 7.0 / 2.0;
//The result of the modulo operation will be 1, //Because if 7 is divided by 3, the remaining is 1 int result = 7 % 3;
Bitwise operators perform operations on bits in the variable. Among them, there exist bitwise logic operations. It means the same logic function is applied to every pair of bits in two arguments. Bitwise or ( | ) means that if at least one bit is “1” at the chosen bit position, the resulting bit will also be “1”. Bitwise and ( & ) means that if at least one bit is “0”, the resulting bit is “0”. Bitwise operators shouldn't be confused with Logic Operators ( || ), ( && ), which operate on a single boolean logic value.
byte result = 5 | 8; ; //The operation in numbers gives the result of 13 ; //in bits can be shown as follows ; // 00000101b ; // 00001000b ; // --------- ; // 00001101b
byte result = 5 & 1; ; //The operation in numbers gives the result of 1 ; //in bits can be shown as follows ; // 00000101b ; // 00000001b ; // --------- ; // 00000001b
Bitwise operators also allow shifting data left ( « ) or right ( » ) chosen number of bit positions. Shifting is often used in embedded programming to access the bit at a specific position. Shifting data one bit left gives the result of multiplication by 2 while shifting one bit right gives the effect of dividing by 2.
byte result = 5 << 1; ; //The operation in numbers gives the result of 10 ; //in bits can be shown as follows ; // 00000101b ; // 00001010b
Compound operators in C/C++ are a short way of writing down the arithmetic operations with variables. All of these operations are done on integer variables. These operands are often used in the loops when it is necessary to manipulate the same variable in each cycle iteration. The compound operators are the following.
int a = 5; a++; //The operation a = a + 1; the result will be 6
int a = 5; a--; //The operation a = a – 1; the result will be 4
int a = 5; a+=2; //The operation a = a + 2; the result will be 7
int a = 5; a-=3; //The operation a = a – 3; the result will be 2
int a = 5; a*=3; //The operation a = a × 3; the result will be 15
int a = 6; a/=3; //The operation a = a / 3; the result will be 2
int a = 5; //The result will be the remaining //Part of the operation a/2; it results in 1 a%=2;
int a = 5; a|=2; //The operation a=a|2; the result will be 7
int a = 6; a&=; //The operation a=a&2; the result will be 2
Simple and complex types can be referred to with the use of pointer variables. A pointer is a variable that holds the address of the variable. The length of the pointer is equivalent to the length of the memory address (usually 16, 32 or 64 bits). A pointer does not contain a value but rather points to the variable (a memory) where the value is stored. A pointer variable must be initialised and dereferenced with Address-Of and Dereferencing operators.
The following example presents a simple type declaration and the use of a pointer variable.
&
operator returns an address of a variable.
*
operator dereferences a variable (it provides access to a value that the pointer variable points to).
int n = 10; //Declare a variable of type int and initialize it with 10 int *ptr; //Declare a pointer variable. //At this point, *ptr does not contain any address yet, //rather some random address or null. ptr = &n; //Assign to the pointer ptr an address of the variable n //ptr contains now an address of the memory where variable n is located, //not a value 10 int k; //Declare another variable k = *ptr; //Assign k a value that is pointed by ptr
Simple type variables such as int, double, float
and so on are passed to the function arguments as values, so the original value is copied, and a copy is presented to the function code (more on functions once can find in the Sub-programs, Functions). Modifications to the argument do not change the original value but just a copy. This is not the case when passing a complex type, such as an array, as an argument.
The importance of pointers is not to be underestimated in this case: you simply declare a pointer pointing to the array's first element and pass it to the function. Then modifying the pointer value (an address), it is possible to refer to the following elements of the array. In this case, any modification to the referred array element modifies an original one, so the change in the value is instant. It does not need a return variable from a function.
A typedef
specifier can give another name for existing types or declares a new one. Renaming types is possible, but software development frameworks used have a number of aliases already. It is helpful, however, when combined with enumerations, classes and structures to give them reasonable names and re-use them later in the code to improve their readability. We present more details on structures in the chapter Structures and Classes, but here is an example presenting a reasonable use of the typedef
specifier.
typedef struct {int x; int y;} tWaypoint; //Declare complex type named waypoint ... //Declare a variable of the type of tWaypoint tWaypoint wp1;
Enumerations are helpful to give meaning to the integer values and present some logic in a code instead of putting numbers into it. It can be, i.e., the device's state, error code, etc.
In the case a new enumeration is needed, it is possible to declare one using the enum
keyword and specifying a list:
enum errorcodes {ER_OK, ER_DOWNLOAD, ER_UPLOAD, ER_NOWIFI}; //define enumeration ... errorcodes Errorcode; //declare a variable ... Errorcode = ER_DOWNLOAD; //assign a value
The default numbering starts with 0 (ER_OK=0
) and increases by 1 with every next item on the enumeration list. However, explicitly defining values represented by the item labels is possible.
enum errorcodes {ER_OK=0, ER_DOWNLOAD=3, ER_UPLOAD=4, ER_NOWIFI=1};