C++, like many programming languages and mathematics in general, is often fussy about the kind or type of values you enter. There are a great number of built-in types in C++, and the language has provisions for you to invent your own.
However, unlike many languages, C++ will sometimes silently convert an object of one type into another type. (For example, it will perfectly happily convert an int that you supplied, when it was expecting a real number, i.e. a double.) Much of the time, this is what you want. Sometimes this causes problems, such as if you give C++ a real number when it expects an integer. C++'s warnings can help warn of possible problems in this regard.
Warning on warnings: Relying on warnings in this way can be problematic. Firstly, you have to remember to enable warnings. Secondly, having done this you are replying on the compiler to issue you with all relevant warnings. But there is no ISO standard on "C++ warnings", so nothing is guaranteed. This could be regarded as a defect in C++, but it is one that you, the programmer, must learn to work around. Nevertheless warnings are often helpful and it is silly not to heed them.
Here is a list of some of the most common types in C++.
All of these types have variations. As just explained, ints can be signed or unsigned, but can also be long or short (i.e. possibly representing more or fewer values) and the same goes for char and double. There is an old version of "real" called float which is probably not worth using any more, unless you really need to speed up your program or reduce the amount of memory it uses and you know what you are doing. There is also an old-style version of string as used in the older language C which I do not recommend for everyday use and especially not for beginners.
Variables are central to imperative programming in languages like C++, and will be discussed in many places in these notes including in more detail later. We look at them briefly here in relation to types.
As know already, you can store values in "registers" or "memories" called "variables". A variable in C++ is not like a variable in maths. It stores some data and has a value at each moment in time, but that value may be changed. A variable in C++ can only store data of one particular type and you have to tell the compiler in advance what variables you propose to use and what types they correspond to. Thus, you must declare variables. For example,
int n;
declares a variable to contain a value of type int. The statement,
double n,k,m;
declares three variables of type double, and
string s;
declares a string variable s.
You can see variables of types string, int and double in the examples given on the page on simple input and output.
It is recommended to give variables an initial value at the time they are declared. (This is more efficient for the computer because all variables when they are available should be given some default value. It is sensible to give them the value(s) you want straight away. Also forgetting to give a variable a value is a frequent source of bugs.) In most cases, the syntax for this is
int numb = 0; double x_unknown = 3.14159; char mychar = '?'; string mystring = "Hello from C++";
In some cases, such as the special complex types built from "double", the initialiser is given in round brackets instead.
complex<double> z(1.1,2.2);
More recent versions of C++ use curly brackets for some initialisers. The reason for having different ways to initialise variables is to do with the history of C++, how it developed from C, and C++'s classes, which are (sadly) outside the scope of this module.
The command for giving a variable a new value is =. More precisely,
var = value;
gives the variable var the value calculated at value. (This is called an assignment command.) In other words = in C++ is completely unlike = in mathematics. In some ways using the symbol = in this way is a particularly unfortunate notation, and other people have suggested alternatives, but none of them has had much popularity.
In an assignment like the one above the types must match. You cannot give a string variable the numeric value 3.14159. (But the string value "3.14159" is OK.) Conversely a double variable cannot get the value "3.14159", but 3.14159 is OK.
string pistring = 3.14159; // type error! string pistring = "3.14159"; // OK! double pi = 3.14159; // OK! double pi = "3.14159"; // type error!
Example.
To demonstrate type errors in initialisers, copy and compile the following.
// types-ex1.cpp (click here to download)
#include <iostream> #include <string> using namespace std; int main () { string pistring1 = 3.14159; // type error! string pistring2 = "3.14159"; // OK! string pistring3 = '3.14159'; // '' can't be used for a string! double pi1 = 3.14159; // OK! double pi2 = "3.14159"; // type error! int n1 = 3.14159; // conversion of double to int, may give warning double n2 = 3; // conversion of int to double, OK! }
The proviso to this rule is that C++ will happily and silently convert between numeric types. Of course you might not be happy about some of these automatic conversions. The GCC warnings that you should enable as a matter of course -Wall will help highlight many bad cases.
Example.
To demonstrate conversions from one type to another without loss of precision,
// types-ex2.cpp (click here to download)
#include <iostream> using namespace std; /* demonstrates automatic conversions between types in C++. None of * these conversions involve any loss of precision, and normally no * warnings will be issued. */ int main () { bool b; char c; int i; double d; b = true; cout << "b == " << b << endl; i = b; // true is converted to 1 cout << "i == " << i << endl; b = false; i = b; // false is converted to 0 cout << "i == " << i << endl; c = 'A' + true; // true->1 so c becomes 'B' cout << "c == " << c << endl; i = c; // character converted to int cout << "i == " << i << endl; d = i; // int converted to double cout << "d == " << d << endl; }
Example.
To demonstrate conversions from one type to another with possible loss of precision,
// types-ex3.cpp (click here to download)
#include <iostream> using namespace std; /* demonstrates automatic conversions between types in C++. All of * these conversions involve some possible loss of precision, so * warnings may be issued, if enabled. */ int main () { bool b; char c; int i; double d; d = 3.1415926; cout << "d == " << d << endl; i = d; // i becomes 3 cout << "i == " << i << endl; c = 'A'+d; // c becomes 'D' cout << "c == " << c << endl; if (d) /* 3.1415926 -> true */ { cout << "true" << endl; } else { cout << "false" << endl; } b = c; // c!=0 so b==true cout << "b == " << b << endl; d = -3.1415926; cout << "d == " << d << endl; i = d; // i becomes -3 cout << "i == " << i << endl; d = 0.14159; if (d) /* 0.14159 not zero -> true */ { cout << "true" << endl; } else { cout << "false" << endl; } b = d; cout << "b == " << b << endl; i = d; // i becomes 0 cout << "i == " << i << endl; if (i) /* i is zero -> false */ { cout << "true" << endl; } else { cout << "false" << endl; } b = i; cout << "b == " << b << endl; // so "b = d;" is not the same as "i = d; b = i;" }
Beware!
The way C++ converts between some of its types is not always simple or obvious, and can be a serious source of bugs and errors. As usual with C++ and the way it is designed, it is intended to make advanced programmers write more efficient code more quickly, and to be compatible with the older language C. It is not designed to help beginners learn more easily. It is probably worthwhile learning the above rules carefully.
As well as the numeric types double and int C++ has operators + - * / on each. ("Star" is multiplication.) These get discussed later.
This is a general feature of C++ that different operators and functions may have the same name or symbol provided they can be distinguished by the number or type of their arguments. This feature is called "overloading" and is another important application of C++'s typing mechanism. You will certainly see it in action, but unfortunately the details of "overloading" are tricky and too advanced for these web pages.