After having covered the basic C++ data types in part 006 of this tutorial, let’s have a look at the definition of constants.
A constant in a program is the same as a mathematical constant: it is an expression of a certain type with a value that does not change during a computation or any run of the program. Mathematics knows generic constants like pi (3.1415…), and in physics there are constants for the speed of light and a lot of other things.
In mathematical equations, there is also the concept of a temporary constant, which is a variable that has a fixed value only for a specific computation, with a possible different value for the next computation.
For a computer program, a constant is just a variable that has a fixed value for the whole runtime of the program.In contrast to a normal variable though, any try to assign a new value to it after the initialization leads to an error.
In addition to that, you always need to set a value for a constant when you define it, whereas variables can be assigned initial values separately after the declaration.
In C++, it is possible to define a constant for most of the basic, build-in data types: char, int, float, long etc.
Just as with variables, depending on the value and how and where you want to use it in your program, you need to be clear about the data type of any constant you define.
In order to define – or directly use – a constant value we need to use a so called “literal” in the related line of code in our program.
A literal is just a specific, concrete value of a given data type. In a direct value assignment such as
where the integer variable “x” is assigned the value “10”, “10” is the literal.
For integer values, the explicit number can be used as a literal, no matter if the value is positive or negative. With a negative integer value, you can just add the minus sign directly in front of the value.
In C++, integer values can also be expressed by using octal (base 8) or hexadecimal (base 16) numbers instead of decimal (base 10) numbers. This can sometimes be useful as these numbers directly relate to the byte-values (1 or 2 bytes) of the variable inside the memory, especially in more technical, hardware-related programs. Octal numbers start with a “0” (zero), followed by one or more digits with values between zero and seven. Hexadecimal numbers start with “0x” (zero followed by “x”) and use digits with values between zero and nine, as well as the characters “a” to “f” (for values between ten and fifteen).
As you know from part 006 of this tutorial, integer variables can be defined with different type modifiers which can suppress the sign before the value (unsigned) or reserve more memory in order to store bigger values (long, long long). If you want to define a constant with the same integer modifiers, you have to add a suffix after the numeric value: “u” or “U” for “unsigned”, “l” or “L” for “long”, “ll” or “LL” for “long long”, or a combination of that.
For floating point numerals, you also need do add a suffix, dependent on the type you want to use. With a value of the type “float”, the suffix is “f” or “F”, and for a “long double” you need to add “l” or “L” to the value.
Apart from standard floating point numbers which consist of some value followed by a point and additional decimals, the numeral for a floating point value can also use the “e”-notation, where “e” stands for the mathematical expression “times ten to the power of”, which is a kind of a shorthand notation for especially big or small values.
Here is an overview of the different kinds of numeric literals with their data type and some examples:
Data type | Suffix | Example | Remarks |
---|---|---|---|
int | 42 -7 052 0x2a |
no suffix necessary negative value octagonal value hexadecimal value |
|
unsigned int | u U |
125u 125U |
only positive values |
long | l L |
130l 130L |
big values |
unsigned long | ul UL lu LU |
65ul 65UL 65lu 65LU |
big, positive values |
long long | ll LL |
240ll 240LL |
huge values |
unsigned long long | ull ULL |
378ull 378ULL |
huge, positive values |
float | f F |
3.14159f 3.14159F |
floating point numbers |
double | 6.952 2.356e4 |
default type for floating point numbers without additional suffix | |
long double | l L |
5.396485e-5L | Note: if the L suffix is used in combination with a floating point number, the compiler assumes that the type is “long double”; if it is used with an integer number, the type is set to “long int”. |
Literals for single characters or strings consist of a single character or a string of characters that is enclosed by quote signs.
For a single character, we need to use the single quotes, for example:
As the examples above show, you can use any kind of character for a single character literal. This includes number characters and escape sequence characters (which I’ve already listed in part 003 of this tutorial).
Note that any number inside quotes is interpreted as a character, not as a number. If you want to use it for any computation, you need to convert it into a numerical type first.
Another thing to keep in mind is the similarity between single character literals and variables which use only a single character as their name:
In the above example, the first “I” is interpreted as the identifier for a variable, while the second “I” is interpreted as a single character literal because of the single quotes.
For string literals, the string of characters has to be put in double quote signs, like this:
As a string can contain any kind of character, you can include special characters, numbers and also escape sequences in your string. Here are some examples:
The second example shows that inside the string literal, any single quote sign is just part of the string. So if you use something like
the character “X” and the surrounding single quotes are contained in the string and will be part of the output if you print this.
If you use more than one string literal in the same line of code – where the single line of code can span more than one line – the literals are automatically interpreted as one single, long literal. For example:
The example above will automatically be combined into a single literal when the program is executed: “The quick brown fox jumps over the lazy dog.” Any spaces, tabs and line breaks outside of the string literals (not between double quotes) are ignored, anything between the double quotes is combined into one string literal.
This concatenation of string literals only happens as long as there is no marked line end, which in C and C++ is a semicolon.
For long string literals which do not fit into a single line of code, you can either concatenate several shorter string literals manually or use the backslash character in order to tell the compiler that the string literal is continued in the next line, like this:
This is equivalent to:
Similar to the different suffixes for numeric literals which let you set the literal value to a specific data type, you can use different prefixes for single character literals and strings.
In the previous part of this tutorial I already listed the different data types for character variables. There are specific prefixes for character literals which refer to these different types, as you can see in the table below:
Data type | Prefix | Example | Remarks |
---|---|---|---|
char | 'A' '\n' |
no suffix necessary | |
char16_t | u | u'B' | 16-bit character |
char32_t | U | U'C' | 32-bit character |
While the string data type is always just a succession of characters that is usually ended with a “null” character, C++ allows two additional variations when it comes to string literals: raw strings and UTF-8 encoded strings.
In a raw string, you can include the backslash, as well as single and double quotes as part of the string in order to include them in the output. A raw string literal can be defined by using the prefix “R”, followed by a double quote and a left bracket, the string data and a right bracket and another double quote. Everything that appears between the two brackets “(“ and “)” will be included in the string output, while any sequence of characters outside the brackets is ignored.
A string with UTF-8 encoding is a Unicode string that uses the UTF-8 encoding for the characters contained within. In contrast to the default ASCII characters, which are identical to the first 128 UTF-8 characters, the Unicode characters cover a wider range of special characters from different languages. Apart from the first 128 characters, they internally use 2 to 4 8-bit bytes to store the character values. You can get more details about UTF-8 on the related Wikipedia page.
Here is a short overview for the different kinds of string literals:
Data type | Prefix | Example | Remarks |
---|---|---|---|
string | "Hello again." | no suffix necessary | |
string (raw) | R | R"(This is a \backslash and some "'quote'".)" R"&%$(another string with \backslash)&%$" |
Anything between "( and )" is included in the string, any sequence of characters outside the brackets is ignored. |
string (Unicode) | u8 | u8"This is a Unicode \x0065 character." | With the "u8" prefix, the string is automatically encoded into a string of Unicode characters using the UTF-8 encoding. |
You can also use literals for the Boolean and null pointer data types. In contrast to numeric or character types, you can only use specific keywords as literals here.
For Boolean values, the allowed keywords are "true" and "false", which directly relate to the Boolean value they represent.
With null pointers, the only allowed keyword literal is "nullptr".
Here is a short example:
Outside of literals which can be used to assign a constant value to a variable, constants can also be defined using explicit data types in the same way that variables are defined. This allows you to use the same value in different parts of your program without having to write down the explicit value again and again. Instead, you can just use the name of the constant that you defined, which also makes the code more readable.
You can turn the definition of any variable that uses a standard data type into the definition of a constant by adding the prefix keyword “const” to the definition and assigning an initial value as part of the definition. For example:
Constants that are defined like this can be used in the same way that variables are used. As with variables, you occasionally might have to do some type conversion for specific computations.
Here is a short example program that uses “typed” constants:
In this short example program you can enter a floating point value for the radius of a circle. The program then takes the input and calculates the circle area using your input and the defined constant for pi. After that, you get an output message followed by the calculated area value.
While typed constants are defined similar to variables, their value cannot be changed when the program is executed. You cannot assign different literal values or calculated values to a constant after the constant has been initialized. Doing so will produce an error.
One last option to define constants in a way that allows you to use them over and over is using preprocessor definitions to define them.
I’ll tell you more about preprocessor definitions in a later part of this tutorial, so I’ll stick to the most important details right now.
Preprocessor definitions are used to replace custom identifiers in your code with a pre-defined replacement. The identifier is a custom, single word name that is written in capital letters, and the replacement can be any literal or string of characters.
A preprocessor definition is defined at the top of the program, after the references to the used libraries and namespaces, before the rest of the code, using the keyword “#define”, like this:
When your program is compiled, the preprocessor checks the code of your program and replaces any identifiers it finds with the replacement you defined, before passing the code to the compiler. This change only happens inside the memory, so your source code will not be changed.
Here is a version of the previous program to calculate a circle area that uses preprocessor definitions instead of the typed constants:
There are two things to look out for if you use preprocessor definitions to define constants:
Now you have an overview of how to define and use constants in your programs. Together with variables – which we covered earlier – this is useful for calculations where you often need the same values as part of the equation several times.
The code for this part of the tutorial can be found in the "Variables-Constants" subdirectory within the complete tutorial code repository on GitHub. If you have git or GitHub Desktop installed on your computer, you can clone the git repository, if not, you can download it as a ZIP archive.
I hope you are coming back for the next part in the C++ with Qt tutorial!