Types in C++

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.

1. The commonly used types

Here is a list of some of the most common types in C++.

bool
The boolean type in C++ is called bool and there are two values, true and false.
int
C++ has a very poor and error-prone type for integers called int. Values of this type are fast to compute with, but not all integers are represented, and as a consequence strange results can occur. Also C++, to run as fast as possible does not warn you when an error occurs. You no doubt have already seen such problems and there are always workarounds. But meanwhile, int is fine for ordinary integers such as -20753421 and many others, as long as they don't get too big. (If you really need longer ints C++ provides long int and long long int which should have larger ranges, but these are still limited and are specific to the platform you are working on. E.g., unfortunately, in MS-Windows "long int" is no better than "int". If you need even bigger integers there are special packages you can use. In this module if you need long int or long long int you'll be told.)
double
C++'s notion of "real number" is (for historical reasons) called double. These values include all the ints and a great deal more besides. Understanding the limitations of double is one of the main objectives of this course. You can write doubles in normal notation such as -3.1415926 or in exponential notation such as 3.234E-45 (meaning 3.234 × 10 -45 ).
unsigned
C++ actually has a number of other "int"-like types, most of which we will not need. One that is occasionally useful in a beginner's course like this is "unsigned". The word unsigned on its own is an abreviation for unsigned int and refers to a kind of int that cannot be negative, usually in the range from 0 to 2 32 - 1 . C++ will convert between unsigned and int if required to, and may not get it right. The unsigned type will be occasonally useful when we are considering arrays, especially when warnings are enabled.
char
C++ has a type for characters, such as 't'. In many ways these characters behave like even-more-limited ints. We will hardly use them here. (There are a number of advanced problems relating to char that will not concern us such as: what character set is being used?. There are thousands of character sets in use today, and for those that need to know about such things, the problems can be very awkward. If this concerns you in a project later on, use packages written by experts and read about the problem carefully before you start. Don't just assume that the easiest solution will always work.)
string
C++ has a type for strings, such as "This is a string". To use this you need #include <string>. This is very useful, and there will be plenty of examples.
complex
C++ has a complex number type, which is essentially a pair of doubles with some nice operations. To use this you need #include <complex>. We will see more of this later.

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.

2. Variables

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.

3. Assignments

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.

4. Overloading

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.