Advanced Introduction to C++, Scientific Computing and Machine Learning




Claudius Gros, WS 2019/20

Institut für theoretische Physik
Goethe-University Frankfurt a.M.

Data Types, Pointers & Memory


primitive data types

Typ Size Domain Example
bool 1 {true, false} bool b = true;
char 1 [0x0000, 0xFFFF] char c = 'a';
byte 1 [−27, 27−1] = [−128, 127] byte b = 4;
short int 2 [−215, 215−1] = [−32,768, 32767] short int s = 12345;
int 4 [−231, 231−1] =
[−2,147,483,648, 2,147,483,647]
int i = 17;
long int8 [−263, 263−1] long int l =8L;
float 4 [1.40239846 ⋅ 10–45, 3.40282347 ⋅ 1038] float f = 3.14F ;
double 8 [4.94065645841246544 ⋅ 10–324,
1.79769131486231570 ⋅ 10308]
double d = 3.14

example: primitive data types

Copy Copy to clipboad
Downlaod Download
#include <iostream>
#include <stdio.h>
#include <complex>  // complex numbers
using namespace std;

int main()
{
 int intArray[5] = { 16, 2, 77, 40, 12071 }; 
 double doubleArray[10];
//
 printf("size of        bool   : %4d\n",(int)sizeof(bool));
//
 printf("size of        char   : %4d\n",(int)sizeof(char));
 printf("\n");
 printf("size of        int    : %4d\n",(int)sizeof(int));
 printf("size of  short int    : %4d\n",(int)sizeof(short int));
 printf("size of   long int    : %4d\n",(int)sizeof(long int));
 printf("\n");
 printf("size of        float  : %4d\n",(int)sizeof(float));
 printf("size of        double : %4d\n",(int)sizeof(double));
 printf("size of   long double : %4d\n",(int)sizeof(long double));  // what is that?
 printf("\n");
 printf("size of      intArray : %4d\n",(int)sizeof(intArray)); 
 printf("size of   doubleArray : %4d\n",(int)sizeof(doubleArray));
//
 typedef complex<double> doubleComplex;
 printf("\n");
 printf("size of doubleComplex : %4d\n",(int)sizeof(doubleComplex)); 
 printf("\n");
//
//
 printf("=== =============================== ===\n");
 printf("=== having fun with complex numbers ===\n");
 printf("=== =============================== ===\n");
 doubleComplex a(1.11,2.22),b(0,1);
 printf("\n");
 printf("a         = %f + %f i\n",a.real(),a.imag());
 printf("\n");
//
 cout << "a         = " << a       << "\n";
 cout << "b         = " << b       << "\n";

 cout << "a + b     = " << a + b   << "\n";
 cout << "a * b     = " << a * b   << "\n";
 cout << "a / b     = " << a / b   << "\n";
 cout << "|a|       = " << abs(a)  << "\n";

 cout << "a*        = " << conj(a) << "\n";
 cout << "norm(b)   = " << norm(b) << "\n";
 cout << "exp(b*pi) = " << exp(b*M_PI)  << "\n";  // check precision !
 printf("\n");
 printf("pi        = %50.48f\n",M_PI);

 return 0;
}

type conversion vs casting

Copy Copy to clipboad
Downlaod Download
#include <iostream>
#include <stdio.h>
#include <typeinfo>    // typeinfo
using namespace std;

int main()
{
//                 implicit type conversion
 short a=2000;
 int b;
 b=a;
 printf("a = %5d,  b = %5d\n",a,b);
 printf("\n");
//                 explicit type conversion
 double x = 10.3;
 int y,z;
 y = int(x);    // functional notation
 z = (int)x;    // c-like cast notation 
 printf("x = %6.3f,  y = %3d,  z = %3d\n",x,y,z);
 printf("\n");
//                 type checking
 if (typeid(a) != typeid(b))
   {
    cout << "a and b are of different types:\n";
    cout << "a is: " << typeid(a).name() << '\n';
    cout << "b is: " << typeid(b).name() << '\n';
  }
//                 converting to strings
 printf("\n");
 int number = 123;     // number to convert
 char strResult[16];   // string (array of char), for the Result
 sprintf(strResult, "%d",number);      // write integer to string
 printf("number = %d,  strResult = %s\n",number,strResult);
//                 converting from strings
 char text[] = "456";  // string to be converted
 int intResult;        // number which will contain the result
 sscanf (text,"%d",&intResult);        // pointer: &intResult
 printf("  text = %s,  intResult = %d\n",text,intResult);
//                 ASCII character table
 printf("\n");
 printf("=== ===================== ===\n");
 printf("=== ASCII character table ===\n");
 printf("=== ===================== ===\n");
 printf("\n");
 for ( int x = 0; x < 128; x++ ) 
   cout << x << ". "<< (char)x << "\n"; 
 printf("\n");
//
 return 0;
}

arithmetic operators

SymbolDescriptionExamples
=assignment int i=5;
+  -addition, subtraction int i=5+3; int i=5-3;
*  /multiplication, integer division int i=5*3; int i=9/3;
%modulo int i=14%3;
+  -unary plus/minus int i=+3; int i=-2;
+=  -=  *=   /=assignment and operation i += 5; // i = i + 5
++   --pre-/postfix increment/decrement i++; // i = i + 1

mathematical functions

Copy Copy to clipboad
Downlaod Download
#include <iostream>
#include <math.h>
using namespace std;

int main()
{
  double number,dsqrt,dpow,dlog,dlog10,expLog;

  cout << "Please enter a number \n";
  cin >> number;

  dsqrt  = sqrt(number);
  dpow   = pow(number,3);
  dlog   = log(number);
  dlog10 = log10(number);
  expLog = log(exp(number));


  cout << "\n";
  cout << "square root of  " << number << "   is : " 
       << dsqrt << "\n";
  cout << "        log of  " << number << "   is : " 
       << dlog << "\n";
  cout << "      log10 of  " << number << "   is : " 
       << dlog10 << "\n";
  cout << "                " << number << "^3 is : " 
       << dpow << "\n";
  cout << " exp of log of  " << number << "   is : " 
       << expLog << "\n";

  return 0;
}

arrays

example: arrays

Copy Copy to clipboad
Downlaod Download
/* compile with  g++             -o test.e test.c  */
/*      or with  g++    -DNDEBUG -o test.e test.c  */
/*                      (turns `assert()' off)     */
//
#include <iostream>         // input/output handling
#include <stdio.h>          // for formatted input/output
#include <assert.h>         // (`assert()' calls abort if arg not true)
#define VARIABLE_NAME(x) #x     // a C++ macro definition
using namespace std;

int main()
{
 int badHabit[10];             // generically bad programming
 const int arrayLength = 10;   // array length need to be constant
 int goodHabit[arrayLength];   // much better programming
//
 cout << "goodHabit has " << sizeof(goodHabit) / sizeof(goodHabit[0])
      << " elements\n\n";
//
 goodHabit[0] = 0;                 // first element
 for (int i=1;i<arrayLength;i++)   // starting at second element
   goodHabit[i] = goodHabit[i-1]+1;
 for (int i=0;i<arrayLength;i++)   
   cout << VARIABLE_NAME(goodHabit) 
        << "[" << i << "] = "
        << goodHabit[i] << "\n";
 printf("=== ==================== ===\n");
 printf("=== array bound checking ===\n");
 printf("=== ==================== ===\n");
 string stringArray[] = {"apple","banana","oranges"};
 for (int i=0;i<6;i++)   
   {
   assert(i>=0);     // array size checking by hand
   assert(i<sizeof(stringArray)/sizeof(string));
   printf("stringArray[%d] = %s\n",i,stringArray[i].c_str());
   }
 return 0;
}

example: matrices

Copy Copy to clipboad
Downlaod Download
#include <iostream>  // input/output handling
#include <stdio.h>   // for formatted input/output
using namespace std;
 
const int X=9;
const int Y=7;
 
int main()
{
 char Spielfeld[Y][X];
 int x, y;
 char cx, cy;
 for (x=0; x<X; x++)
   for (y=0; y<Y; y++)
     Spielfeld[y][x] = '.';
//
// Anzeige und Eingabe
//
  bool SchleifenEnde=false;
  int xin, yin;
  do {
     printf("  ");
     for (x=0; x<X; x++)
       printf("%3d",x+1);
     printf("\n");
//
     for (y=0; y<Y; y++)
       {
       cout << (char)('A'+y) << " ";
       for (x=0; x<X; x++)
         printf("%3c",Spielfeld[y][x]);
       cout << endl;
       }
//
  cout << "your hit: ";
  cin >> cy >> cx;
  xin = cx - '1';
  yin = cy - 'A';
  if (xin>=0 && xin<X && yin>=0 && yin<Y)
    {
    Spielfeld[yin][xin] = 'x';
    cout << "# (yin,xin): (" << yin
         << "," << xin
         << ")\n\n";
    }
   else
    SchleifenEnde = true;
    } while (!SchleifenEnde);
}

C++ pointers

Copy Copy to clipboad
Downlaod Download
#include <iostream>
 
using namespace std;
 
int main ()
{
 int var1   = 20;  
 int var2[] = {1,2,3};  
 
 cout << endl;
 cout << "address of var1: " << &var1 << endl;
 cout << "address of var2: " <<  var2 << endl;
 cout << "address of var2: " << &var2 << endl;
 
 int* ip;         // pointer variable 
 ip = &var1;      // store address of var1 in pointer variable ip
 
 cout << endl;
 cout << "value of var1: " << var1 << endl;
 cout << "value of   ip: " <<   ip << endl;
 cout << "value of  *ip: " <<  *ip << endl;
 
 ip = var2;       // not &var2 (!), since arrays are already pointers
 for (int i=0; i<3; i++)
   {
   cout << endl;
   cout << "address of var2[" << i << "] = "
        << ip << " " 
        << &(*ip) << " "
        << &var2[i] << endl;
 
   cout << "  value of var2[" << i << "] = "
        << *ip << " "
        << *(&(*ip)) << " "
        << *(&var2[i]) << endl;
 
   ip++;          // point to the next location (errors likely)
   }
 
 return 0;
}

dynamic memory

Copy Copy to clipboad
Downlaod Download
#include <iostream>      // standard IO
#include <cstdlib>       // for atof
 
using namespace std;
 
int main(int argLength, char* argValues[])   // parsing command line arguments
{
 if (argLength==1)
   {
   cout << "please run with an long integer argument\n";
   return 0;
   }
 long int dynamicArraySize = atof(argValues[1]);  // casting string to long
 long int gigaByte = 1073741824;
//
 cout << endl;
 cout << "trying to construct integer arrays of size : "
      << dynamicArraySize << endl;
 cout << "using  "
      << dynamicArraySize*sizeof(int)*1.0/gigaByte 
      << "  Gigabytes of memory " << endl << endl;
//
 int array_1[dynamicArraySize];            // not all compilers like that
 cout << "sizeof(array_1)  : "
      <<  sizeof(array_1) << endl;
//
 int *array_2 = new int[dynamicArraySize]; // arrays are pointers
 cout << "sizeof(array_2)  : "
      <<  sizeof(array_2) << endl;
 
 int *array_3 = new(nothrow) int[dynamicArraySize];
//
 if (array_3 == 0)                         // controlled exit for null pointer
  {
  cout << "I am out of memory" << endl;
  return 0;                                // program failed
  }
 cout << "sizeof(*array_3) : "
      <<  sizeof(*array_3) << endl;
//
 cout << "sizeof(int)      : "
      <<  sizeof(int) << endl;
//
 delete[] array_2;      // deletes the whole array
 delete array_3;        // deletes only the first element
//
 return 1;
}

memory usage

Copy Copy to clipboad
Downlaod Download
#include <iostream>      // standard IO
#include <stdio.h>       // for printf
#include <cstdlib>       // for atof
#include <math.h>        // for the math
#include <time.h>        // ('clock()' measures time in nanoseconds)
     
using namespace std;
     
const long int oneGigaByte = 1073741824;   // one Giga Byte
 
/* **************************************** */
/* *****      time in seconds       ******* */
/* **************************************** */
 
double timeInSeconds()
{
const double oneSecond = 1.0 / CLOCKS_PER_SEC;
static long int lastTime = clock();
long int actual_time = clock();
long int elapsed_time = actual_time - lastTime;
lastTime = actual_time;
return elapsed_time * oneSecond;     // time passed since last call
}    
 
/* **************************************** */
/* *****            main            ******* */
/* **************************************** */
     
int main(int argLength, char* argValues[])  // parsing command line arguments
{
 if (argLength==1)
   {
   cout << "please run with a double argument (memory in GB)\n";
   return 0;
   }
 long int dynamicArraySize = (long)(atof(argValues[1])*oneGigaByte*1.0/sizeof(int));  
 timeInSeconds();                           // initialized
 
 int onePerCent = (int)(dynamicArraySize/100);
//
 int *aa = new int[dynamicArraySize];
/*
 for (int i=0;i<dynamicArraySize;i++)
 for (long int i=0;i<dynamicArraySize;i++)
*/
 for (size_t i=0;i<dynamicArraySize;i++)
   {
   aa[i] = i;
   if ((i%onePerCent)==0)
     printf("(main) %5.2f GB indices allocated, %5.2f seconds used\n",
            i*1.0/oneGigaByte, timeInSeconds());
   }
//
 printf("\n");
 printf("(main) starting infinite loop\n\n");
//
 while (true)                   // infinite loop
  double a = log(34545.3454);
//
 return 1;
}

aliasing

Copy Copy to clipboad
Downlaod Download
#include <iostream>       // standard IO
using namespace std;

int main()
{
 double  a = 10.0;
 double& b = a;          // an alias

 cout << "a  = " << a << endl;
 cout << "b  = " << b << endl << endl;
 
 double *pA = &a;
 double *pB = &b;

 b = 6.0;

 cout << "*pA = " << *pA << endl;
 cout << "*pB = " << *pA << endl;

 return 1;
}