Chapter 1
From C to C++

Kurt Nørmark
Department of Computer Science, Aalborg University


Abstract
Next lecture
Index References Contents
In this lecture we will first give an introduction to the course, in particular the first part (the first six lectures) of the course. Following that we will review the most important part of C, in particular for the benefit of those students who have programmed in C the last couple of years. This is also an introduction to the most basic parts of C++.


Course Introduction

The Study Regulation
Slide Contents Index
References 

An elective course

The study regulation for Advanced Programming is not very specific. It enumerates possible topics

  • Knowledge

    • New tendencies as well as classical subjects

    • Libraries and library design

    • Syntactic abstractions and language extensions

    • Declarative, generic, concurrent, reactive programming

    • Types and typeless programming

    • Scripting

    • Module concepts

    • Different hardware platforms

    • Resource awareness

    • Optimizations and performance

  • Skills

    • Choose the right programming language for the task

    • Write correnct, efficient, and maintainable programs

    • Evaluate the use of resources

    • Perform optimizations and carry out performance studies

  • Competences

    • Solving advanced programming tasks

Course Literature
Slide Contents Index
References 

You are recommended to buy and read two books in this course

  • AP1

    • We read selected parts of The C++ Prog. Lang. (4. edition) by Bjarne Stroustrup

    • The course follows the structure of this book

    • An advanced book for an advanced course

  • AP2

    • Based on the topics addressed in Effective Modern C++ by Scott Meyers

    • Advice and best practices for professional C++ programmers

Overview of Advanced Programming - Part One
Slide Contents Index
References 

In the first six lectures we will obtain an overview of C++

  • From C to C++

    • A quick tour of C

    • Types, expressions, functions, parameters, memory allocation, libraries, ...

  • Basic Facilities in C++, in two lectures

    • Basic facilities beyond C

    • Objects, strings, references, vectors, casting, lambda expresssions, function overloading, IO, free store, program organization ...

  • Abstraction Mechanisms in C++, in two lectures

    • The parts of C++ related to OOP

    • Templates

  • Standard Template Library, generic programming and metaprogramming

Overview of Advanced Programming - Part Two
Slide Contents Index
References 

The last six lectures cover technical and advanced details of C++

These lecture will follow the structure of the book Effective Modern C++ by Scott Meyers

  • The AP2 topics include (but are not limited to):

    • Type deduction

    • Smart Pointers

    • Universal References

    • Exception Handling

    • More about lambda expressions

    • Concurrency features

One of the goals of AP1 is to enable you to read the book intended for AP2

Recommended use of your time
Slide Contents Index
References 

The Advanced Programming course is a 5 ECTS course - 150 hours

  • Course part 1:   75 hours

    • Lectures and exercises: 25 hours

    • Reading selected parts of the book: 25 hours

    • Miniproject - selected topic of interest: 25 hours

  • Course part 2:   75 hours

    • Details pending...

Course Approach - Part 1
Slide Contents Index
References 

C++ as compared with similar programming languages, such as C and C#

  • Lectures

    • Traditional lecturing with slides and many small illustrative programs

    • Discussions based on the programming experience and background of the partipants

  • Exercises

    • Small programming exercises

    • Work on the selected topic of interest

  • Selected topic of interest

    • A relatively narrow and delimited topic related to C++, and programming in C++

    • The evaluation of the course is based on documentation of your work on the selected topic

  • Preparation

    • Reading selected parts of The C++ Prog. Lang. (4. edition) and other relevant pieces of literature

    • Programming

Course Exam
Slide Contents Index
References 

The course is evaluated through two miniproject (submissions)

See also the separate document Goals for the first submission in Moodle

Reference

  • Submission one:

    • Select a topic related to C++ which you find interesting

    • Explore the topic alone, or in pairs of two students

    • Do some programming as part of your exploration (individually)

    • Work with this topic during the last couple of exercise slots in the first part of the course

    • Document your efforts in a small report (individually)

  • In submission one it is required that each student individually:

    • Describe and clarify the topic, involving relevant course literature

    • Reflect on the topic relative to his/her experience obtained in prerequisite courses

    • Write a non-trivial, relatively small C++ program that illustrates the topic

    • Compare with another relevant programming languages (such as C or C#).

    • Document his/her efforts in a short (6 page) report/essay

The two submissions are evaluated. The result is a single 7-step grade. There will be an internal examinor (dk: censor). There is no additional oral nor written exam in the course.

Course Features - Part1
Slide Contents Index
References 

A couple of noteworthy features of the AP1 homepage and slides

  • Reading guides

    • Remarks and recommendations relative to the book The C++ Prog. Lang. (4. edition)

    • The references to version 3 of the book are still present The C++ Prog. Lang. (4. edition)

  • References from these slides to the text books

    • Direct references to a particular page

    • Also references to some items in Effective Modern C++

Reference
  • The C++ Prog. Lang. (3. edition): Sample reference: Introduction. Page 1

Reference
  • The C++ Prog. Lang. (4. edition): Sample reference: Introduction. Page 1

Which compiler or IDE?
Slide Contents Index
References 

You are supposed to choose your C++ compiler and/or IDE today

  • Selection mode:

    • Either write C++ program in an environment you already know

    • Or try something new

  • Possibilities

    • Netbeans (with MinGW option)

    • Eclipse

    • Visual Studio

      • Commercial version

      • Free version - Express

    • CodeBlocks

    • GNU's g++ compiler and your favorite text editor

    • Others as well

For the purposes of this course (spring 2015) I use g++ version 4.9.2 via Cygwin on Windows with GNU Emacs

C++11 support via a compiler option -std=c++11. Experimental C++14 support via -std=c++14

Where to find C++ documentation
Slide Contents Index
References 

www.cplusplus.com/reference is the place to look for C++ library documentation

There is also an easy tutorial at the site


A quick tour of C

Basic Observations
Slide Contents Index
References 

Characteristics of the C programming language

  • Imperative programming language

    • State and mutation; arrays, structs and pointers; assignment and basic control structures

  • Terse, low level and permissive

  • Efficient code and resource awareness

    • Generation of machine code

    • No virtual machine

  • Accompanied by a preprocessor language

    • Textual substitutions carried out before the traditional compilation process

  • The mother language of many important, contemporary programming languages

    • The original language in the C-family

The Evolution of C
Slide Contents Index
References 

  • Traditional C

    • Pre standardization C

    • Relates to version 1 of Kernighan and Ritchie's book The C Programming Language

  • Standard C - ANSI C - C89

    • Still the most widespread version of C

    • The version supported by most compilers, and text books

    • Relates to version 2 of Kernighan and Ritchie's book The C Programming Language

  • C99

    • A major new version relative to C89, with many new features

    • Developed in parallel with C++

  • C11

    • Multithreading, improved unicode support, ...

The Popularity of C and C++
Slide Contents Index
References 

The TIOBE programming community index - February 2013

Figure. The TIOBE Programming Language Community Index, February 2013

Reference

The C preprocessor
Slide Contents Index
References 

For definition of symbolic constants and file inclusion

  • #include

    • #include <stdio.h>

    • #include "myfile.h"

    • Typically used for inclusion of header files

  • #define

    • #define PI 3.14159

    • #define product(x,y) ((x)*(y))

    • Definition of symbolic constants and function-like abstractions

  • #if ... #else ... #endif

    • #ifdef ...

    • ifndef ...

    • For conditional compilation

Fundamental types
Slide Contents Index
References 

The most fundamental types are numeric types

  • void

    • The no value type

    • Also used for no parameters, void f(void), and for generic pointer, void*

  • Integer types

    • int, long and short, signed and unsigned

    • The ranges depend on the implementation

  • Pointer types

  • Floating point types

    • float and double, long double

    • The ranges depend on the implementation

  • No boolean type in C89

    • Relies on certain conventions for use of numeric types as integer types

  • Character types

    • A char is a byte

    • Denoted with single quotes: 'A', 'a', '\n', '\141', '\x61'

    • In reality small integers - signed or unsigned

    • Wide characters are also supported

C is a strongly typed, weakly checked language [Dennis Ritchie]

Pointers
Slide Contents Index
References 

Pointers are abstractions of memory addresses

  • A pointer can be constructed by use of the address operator &

  • A pointer must be explicitly dereferenced if we want to access the target value of the pointer

    • By means of the dereference operator *

  • In C you can work on both a pointer and the object pointed to

    • Pointer arithmetic

  • A pointer of type T* to can point to a single value of type T, or to an array of T-values

    • We cannot separate these two situations

  • For two different types T and S: T* is different from S*

  • Generic pointer type void*

  • NULL pointer value

Pointers are also important in C++

May instances of classes or structs are not accessed by pointers in C++

Polymorphic objects must be accessed by pointers, however

C++ smart pointers are introduced to avoid memory leaks and dangling pointers

Arrays and Pointers
Slide Contents Index
References 

Arrays and pointers are closely related in C

The compiler translates all array notations to pointer notation

  • Array basics in C

    • Consecutive memory, elements of same type, fixed size after allocation, size known by the compiler

    • 0-based indexing, subscripting a[i], no range checking

  • Array limitations in C

    • Cannot be assigned to each other, cannot be passed by value, cannot be returned by value

    • In other words: value semantics is not used for arrays in C

  • Strings in C

    • A string is zero terminated, mutable char array

    • of type char[] or char*

    • "string-literals" - denoted with double quotes

    • Supported <string.h> standard library

C++ supports a type parameterized class vector, and a class string, both with value semantic

Arrays and Pointers: Examples
Slide Contents Index
References 

Some programs that illustrate arrays and pointers in C

Program: C Program with an array.
#include <stdio.h>
#include <stdlib.h>

int main(void) {

  double a[] = {1.0, 2.0, 3.0, 4.0, 5.0},
         sum = 0.0;
  int i;

  a[1] = 2.2;

  for (i = 0; i < 5; i++)
    sum += a[i];
  printf("Sum = %f\n", sum);   /* 15.2 */

  return 0;
}

Program: C++ preview: Similar program with vectors - variation 1.
#include <iostream>
#include <vector>

int main(){
  std::vector<double> a{1.0, 2.0, 3.0, 4.0, 5.0};
  double sum = 0;

  a[1] = 2.2;

  for(auto el: a){
    std::cout << el << std::endl;
    sum += el;
  }

  std::cout << "Sum = " << sum << std::endl;  // 15.2

  return 0;
}

Program: C++ preview: Similar program with vectors - variation 2.
#include <iostream>
#include <vector>

int main(){
  using std::vector;
  using std::cout; 
  using std::endl;

  vector<double> a{1.0, 2.0, 3.0, 4.0, 5.0};
  double sum = 0;

  a[1] = 2.2;

  for(auto el: a){
    cout << el << endl;
    sum += el;
  }

  cout << "Sum = " << sum << endl;  // 15.2

  return 0;
}

Program: C++ preview: Similar program with vectors - variation 3.
#include <iostream>
#include <vector>

int main(){
  using namespace std;

  vector<double> a{1.0, 2.0, 3.0, 4.0, 5.0};
  double sum = 0;

  a[1] = 2.2;

  for(auto el: a){
    cout << el << endl;
    sum += el;
  }

  cout << "Sum = " << sum << endl;  // 15.2

  return 0;
}

Program: A similar C program with pointers and dynamic allocation of memory - one dimensional.
#include <stdio.h>
#include <stdlib.h>

int main(void) {

  double *a = (double*)malloc(5 * sizeof(double)),
         sum = 0.0;
  int i, j, k;

  if (a == NULL){
    printf("Memory allocation problem. Bye\n");
    exit(EXIT_FAILURE);
  } 

  for (i = 0; i < 5; i++)      /* Initialize a */
    *(a+i) = (double)(i + 1);

  *(a+1) = 2.2;                /* a[1] = 2.2;  */

  for (i = 0; i < 5; i++)
    sum += *(a+i);
  printf("Sum = %f\n", sum);   /* 15.2         */

  free(a);

  return 0;
}

Program: C Program with two a dimensional array.
#include <stdio.h>
#include <stdlib.h>

int main(void) {

  double b[][3] = {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}},
         sum1 = 0.0, sum2 = 0.0;
  int i, j, k;

  b[1][2] += 0.1;

  for (i = 0; i < 2; i++)      /* Sum of elements */
    for (j = 0; j < 3; j++){
      printf("b[%d][%d] = %f\n", i, j, b[i][j]);
      sum1 += b[i][j];  
    }

  for (k = 0; k < 2 * 3; k++)  /* An alternative summation */
    sum2 += *(&b[0][0] + k);   /* Same result */

  printf("Sum1 = %f, sum2 = %f\n", sum1, sum2);
  /* Sum1 = 21.100000, sum2 = 21.100000 */
  
  return 0;
}

Program: A similar C program with pointers - two dimiensional.
#include <stdio.h>
#include <stdlib.h>

int main(void) {

  double *b = malloc(2*3 * sizeof(double)),
         sum1 = 0.0, sum2 = 0.0, *p;
  int i, j, k;

  for(i = 0; i < 2*3; i++)         /* Initialization   */
    *(b+i) = (double)(i+1);

  *(b + 3*1+2) += 0.1;             /*  b[1][2] += 0.1; */

  for (i = 0; i < 2; i++)          /* Sum of elements  */
    for (j = 0; j < 3; j++){
      printf("b[%d][%d] = %f\n", i, j, *(b + 3*i+j));  
      sum1 += *(b + 3*i+j);        /* sum1 += b[i][j]; */  
    }

  for(i = 0; i < 2*3; i++){        /* Alt summation    */
    printf("el %d: %f\n", i, *(b+i));
    sum2 += *(b + i);   
  }

  printf("Sum1 = %f, sum2 = %f\n", sum1, sum2);
                /* Sum1 = 21.100000, sum2 = 21.100000  */
  
  return 0;
}

Program: Illustration of array limitations in C: Cannot assign.
#include <stdio.h>


int main(void) {

  double a[10], b[10];
  int i;

  for(i = 0; i < 10; i++)  /* Initialization */
    a[i] = i;

  b = a;  /* Compiler error: incompatible types when assigning
             to type double[10] from type double *          */

  for(i = 0; i < 10; i++)
    printf("b[%d] = %f\n", i, b[i]);

  return 0;
}

Program: A solution: Copy the array in a for loop.
#include <stdio.h>


int main(void) {

  double a[10], b[10];
  int i, j;

  for(i = 0; i < 10; i++)  /* Initialization */
    a[i] = i;

  for(j = 0; j < 10; j++)  /* Copy a to b */
    b[j] = a[j];

  for(i = 0; i < 10; i++)
    printf("b[%d] = %f\n", i, b[i]);

  return 0;
}

Program: A solution: Copy the array with memcpy - a low-level alternative.
#include <stdio.h>
#include <string.h>

int main(void) {

  double a[10], b[10];
  int i;

  for(i = 0; i < 10; i++)  /* Initialization */
    a[i] = i;

  memcpy(b, a, sizeof(double)*10);

  for(i = 0; i < 10; i++)
    printf("b[%d] = %f\n", i, b[i]);

  return 0;
}

Program: Illustration of array limitations in C: Cannot pass as value parameter.
#include <stdio.h>

void f (double p[], int p_lgt){    /* Double the elements in p */
  int i;

  for(i = 0; i < p_lgt; i++)
    p[i] = p[i] * 2;  /* p is NOT a local copy of the
                         actual parameter. It is a pointer
                         to the actual parameter array. */
}

int main(void) {

  double a[10];
  int i;

  for(i = 0; i < 10; i++)  /* Initialization */
    a[i] = i;

  f(a, 10);  /* The array a is not copied to f.
                No compiler errors. No run time errors. */

  for(i = 0; i < 10; i++)
    printf("After calling f: a[%d] = %f\n", i, a[i]);

  return 0;
}

Program: Less confusing version that uses pointers.
#include <stdio.h>

void f (double *p, int p_lgt){    /* Double the elements in p  - notice the pointer notation */
  int i;
  double *q;

  for(i = 0, q = p; i < p_lgt; i++, q++)
    *q *= 2; 
}


int main(void) {

  double a[10];
  int i;

  for(i = 0; i < 10; i++)  /* Initialization */
    a[i] = i;

  f(&a[0], 10);    /* Alternative parameter.
                      Maybe less confusing   */

  for(i = 0; i < 10; i++)
    printf("After calling f: a[%d] = %f\n", i, a[i]);

  return 0;
}

Program: Output from both of the two programs above.
After calling f: a[0] = 0.000000
After calling f: a[1] = 2.000000
After calling f: a[2] = 4.000000
After calling f: a[3] = 6.000000
After calling f: a[4] = 8.000000
After calling f: a[5] = 10.000000
After calling f: a[6] = 12.000000
After calling f: a[7] = 14.000000
After calling f: a[8] = 16.000000
After calling f: a[9] = 18.000000

Exercise 1.2. C Time functions from time.h

This exercise illustrates the frustrations that may occur if we (ab)use global variables and pointers. We will play with simple programs that use the standard C library time.h. Recently, a student in 'Imperative Programming' told me that he had used a lot of time on these functions, and he could not figure out why he got wrong results...

A very short explanation of the time functions in C: Time can be represented as 'unix time' (the the number of seconds elapsed since January 1, 1970) with use of the type time_t (just an unsigned integer). Time can also be encoded as a struct, of type struct tm (or in C++ just tm) with fields for seconds, minutes, hours, day, month, year (and more). The function time returns the current time, as a value of type time_t. The function localtime encodes (a pointer to) a unix time. The function asctime returns a textual presentation of (a pointer to) a tm struct. There are a few additional functions, which you may explore yourself.

The following C++ program works as expected:

#include <iostream>
#include <ctime>
#include <string>

using namespace std;

int main(){

  time_t t1 = time(NULL),                                // Time now
         t2 = t1 - 7 * 24 * 60 * 60;                     // Same time last week.

  tm *tm1 = localtime(&t1);                              // Transforms t1 to tm struct
  char *tmstr1 = asctime(tm1);                           // Make an ASCII text string of the time
  cout << "Time now: "<< tmstr1 << endl;                 // Print it

  tm  *tm2 = localtime(&t2);                             // Transforms t2 to tm struct
  char *tmstr2 = asctime(tm2);                           // Make an ASCII text string of the time
  cout << "Time a week ago: " << tmstr2 << endl;         // Print it
}

Try it out - and play with some variations if you want to explore the possiblities with time.h functions. It is a C++ program, so compile it with your C++ compiler.

The following program - where we have reordered some of the commands - does not work as expected:

#include <iostream>
#include <ctime>
#include <string>

using namespace std;

int main(){

  time_t t1 = time(NULL),                                // Time now.
         t2 = t1 - 7 * 24 * 60 * 60;                     // Same time last week.

  tm *tm1 = localtime(&t1);                              // Transforms t1 to tm struct
  char *tmstr1 = asctime(tm1);                           // Make an ASCII text string of the time

  tm  *tm2 = localtime(&t2);                             // Transforms t2 to tm struct
  char *tmstr2 = asctime(tm2);                           // Make an ASCII text string of the time

  cout << "Time now: "<< tmstr1 << endl;                 // Print time now
  cout << "Time a week ago: " << tmstr2 << endl;         // Print time a week ago. Upps - what happened?
}

Make sure you understand the problem(s). How does localtime deliver its result (a tm struct)? An similarly, how does asctime deliver its result (a C-style text string)? Consult the documentation of the time.h library.

Be sure to understand the problems in terms of global data, memory allocation, and pointers.

Why do you think the designers of time.h came up with the signatures of these functions, and the conventions for the use of the functions?

How would you design the functions in order to eliminate the frustrations?

Structures and Unions
Slide Contents Index
References 

A struct aggregates fields of different types to a new composite type

A union is the poor man's - the C programmer's - way of specializing a struct in two or more directions

  • Struct basics

    • Consequtive memory (maybe slighly more than needed), fields of different types

    • Direct component selection str.field - dot notation

      • Also indirect component selection from a pointer to a struct: str_ptr->field

    • Bit fields: Access to selected bits in a field of integer type

  • Union basics

    • A structure where all fields occupy the same memory

    • No way to inquire about the actual type of contents

    • Can be (mis)used to discover details about the representation of data

  • Value semantics

    • Copied when passed as parameters

    • Copied when returned from function

    • If value semantics is too costly, pointers to structs can be used

The C struct is an important starting point of the C++ abstraction mechanisms and OOP

Structures: Examples
Slide Contents Index
References 

Some C programs that illustrate structs in C

Program: C program with a couple of structs.
#include <stdio.h>
#include <stdlib.h>

typedef struct{
  char road[15];
  int roadNumber;
  char town[20];
  } address;   

typedef struct{
  int idNumber;
  char firstName[10],
       lastName[20];
  address location;
  } person;   

void print_person(const person p){
  printf("%s %s\n%s %-4d\n%s\n\n",
          p.firstName, p.lastName,
          p.location.road, p.location.roadNumber,
          p.location.town);
}

int main(void) {
  person morten = 
     {190583,                             /* Initializer      */
      "Morten", "Madsen",                 /* and only that... */
      {"Bredgade", 23, "Middelfart"}
     };

  print_person(morten);

  printf("Size of morten: %d bytes =" 
         "size of person type: %d\n\n",
          sizeof morten, sizeof(person));  /* 76 bytes */
  
  return 0;
}

Program: Program output.
Morten Madsen
Bredgade 23
Middelfart

Size of morten: 76 bytes =size of person type: 76

Program: A move_person function with structs parameters - does not work.
#include <stdio.h>
#include <stdlib.h>

typedef struct{
  char road[15];
  int roadNumber;
  char town[20];
  } address;

typedef struct{
  int idNumber;
  char firstName[10],
       lastName[20];
  address location;
  } person;

void print_person(const person p){
  printf("%s %s\n%s %-4d\n%s\n\n",
          p.firstName, p.lastName,
          p.location.road, p.location.roadNumber,
          p.location.town);
}

/* PROBLEMATIC! Compiles, runs, but does not work as intended */
void move_person(person p, address new_address){
  p.location = new_address;
}

int main(void) {
  person morten = 
     {190583,                             // Initializer
      "Morten", "Madsen",
      {"Bredgade", 23, "Middelfart"}
     };
  address aalborg_address = 
     {"Boulevarden", 33, "Aalborg"};

  print_person(morten);
  move_person(morten, aalborg_address);
  print_person(morten);
  
  return 0;
}

Program: Program output.
Morten Madsen
Bredgade 23
Middelfart

Morten Madsen
Bredgade 23
Middelfart

Program: A move_person function with structs parameters - now better.
#include <stdio.h>
#include <stdlib.h>

typedef struct{
  char road[15];
  int roadNumber;
  char town[20];
  } address;

typedef struct{
  int idNumber;
  char firstName[10],
       lastName[20];
  address location;
  } person;

void print_person(const person p){
  printf("%s %s\n%s %-4d\n%s\n\n",
          p.firstName, p.lastName,
          p.location.road, p.location.roadNumber,
          p.location.town);
}

void move_person(person *p, address new_address){
  p->location = new_address;
}

int main(void) {
  person morten = 
     {190583,                            
      "Morten", "Madsen",
      {"Bredgade", 23, "Middelfart"}
     };
  address aalborg_address = 
     {"Boulevarden", 33, "Aalborg"};

  print_person(morten);
  move_person(&morten, aalborg_address);
  print_person(morten);
  
  return 0;
}

Program: Program output.
Morten Madsen
Bredgade 23
Middelfart

Morten Madsen
Boulevarden 33
Aalborg

Exercise 1.4. Functions with struct input and struct output

Change the program from above such that also the new address of a person is passed as a pointer to a structure. I.e, in this version both parameters to move_person should be pointers.

Program yet another version that returns a moved person from the function (via return). The input person should not be changed. In this version of the program, you may choose to use pure call-by-value parameters (just relying on the value semantics of structs).

There is continuation of this exercise later in the material.

Exercise 1.4. Specialization of persons with a union type

2014 and 2015: I do not recommend that you spend time on this exercise...

Introduce two variants of persons, as introduced in the C program on the accompanying slide.

  • Persons who live at a specific location.
  • Homeless persons, without location and without any id.

Introduce two different person types, and a union that allows us to represent either a 'person with a home address' or a 'homeless person'.

You can read about unions in The C++ Prog. Lang. (3. edition) section C.8.2.

Program: A program that illustrates a struct with bit fields.
#include <stdio.h>

struct pixel {
  unsigned int red:   8;
  unsigned int green: 8;
  unsigned int blue:  8;
};

typedef struct pixel pixel;

pixel make_pixel(unsigned int red, unsigned int green, unsigned int blue){
  pixel p;
  p.red = red; p. green = green; p.blue = blue;
  return p;
}

unsigned int get_red(pixel p){
  return p.red;
}

unsigned int get_green(pixel p){
  return p.green;
}
unsigned int get_blue(pixel p){
  return p.blue;
}


int main(void) {

  pixel p;

  p = make_pixel(80, 90, 100);
  printf("Pixel info: red = %d, green = %d, blue = %d\n", 
          get_red(p), get_green(p), get_blue(p));

  printf("Size of a pixel pixel: %d bytes\n", sizeof(pixel));
  
  return 0;
}

Program: Program output.
Pixel info: red = 80, green = 90, blue = 100
Size of a pixel pixel: 4 bytes

Function types
Slide Contents Index
References 

Functions in C can be used as data of function type

  • Only two possible operations on a function

    • Calling the function

    • Take the address of the function

  • Functions as types and data

    • Dealt with by means of function pointers

    • Use of the dereference operator and the address operator is often implicit

    • Functions are first class data in C, but they are not closures

    • The declaration syntax is obscure - difficult to read

Program: C program with function pointer.
#include <stdio.h>

void (*f)(char *, int);

void fun1(char *s, int i){
  printf("fun1: %s, %d\n", s, i);
}

void fun2(char *s, int i){
  printf("fun2: %s, %d\n", s, i);
}

int main(void) {
  int cond;

  printf("Enter condition (0, 1): ");
  scanf(" %d", &cond);

  if (cond)
     f = &fun1;
  else
     f = &fun2;

  (*f)("AP", 8);
  
  return 0;
}

Program: Same program - without explicit use of the address and dereferencing operators.
#include <stdio.h>

void (*f)(char *, int);

void fun1(char *s, int i){
  printf("fun1: %s, %d\n", s, i);
}

void fun2(char *s, int i){
  printf("fun2: %s, %d\n", s, i);
}

int main(void) {
  int cond;

  printf("Enter condition (0, 1): ");
  scanf(" %d", &cond);

  if (cond)
     f = fun1;
  else
     f = fun2;

  f("AP", 8);
  
  return 0;
}

Program: Same program - using a typedef to capture the function type.
#include <stdio.h>

typedef void (*FUN)(char *, int);

void fun1(char *s, int i){
  printf("fun1: %s, %d\n", s, i);
}

void fun2(char *s, int i){
  printf("fun2: %s, %d\n", s, i);
}

int main(void) {
  int cond;
  FUN f;

  printf("Enter condition (0, 1): ");
  scanf(" %d", &cond);

  if (cond)
     f = fun1;
  else
     f = fun2;

  f("AP", 8);

  return 0;
}

Exercise 1.5. An array of functions

Make an array of structs. The struct should have two fields: A text string and a function pointer. The functions in the struct should accept an integer and a text string.

On top of this, program a function, activator, which activates one of the functions in the array. The function should accept the array (of structs) and a text string. Based on the text string, the activator should search the array for a suitable function. When found, the function should be called.

Relate the setup in this exercise to your knowledge of class hierarchies with virtual functions.

C++ supports lambda expressions (closures)

C++ also supports function objects (by overload of operator() such that an object my be used as a function

References

User defined types
Slide Contents Index
References 

  • Enumeration types

    • A thin layer on top of integers

    • Enumeration constants are not available in the executing program

      • Mapping from integers to symbolic names in switch statements

    • enum class: strongly typed and scoped (C++11)

Reference
  • The C++ Prog. Lang. (4. edition): enum class. Page 50

Reference
  • Effective Modern C++: Prefer scoped enums to unscoped enums. Item 10

  • Structs

    • An aggregate type

    • A value type in C, as well as in C++

  • Typedef

    • A type alias facility

    • Good for complicated and convoluted types, such as function types

Reference
  • The C++ Prog. Lang. (4. edition): Type aliases. Page 167

C++ expands heavily on the user defined types in C

In C++11 type aliases - as well as template aliases - are typically expressed with using instead of typedef

Reference
  • Effective Modern C++: Prefer alias declarations to typedefs. Item 9

Expressions and operators
Slide Contents Index
References 

Expressions and operators in C are well-known

Similar to the means of expression in most other languages in C family

  • Expressions are evaluated to obtain a value

  • Expressions in C may have side effects

    • Assignments are expressions

    • Other dirty operators: ++, -- (both prefix and postfix)

  • Operators

    • In C: A fixed repertoire with fixed meanings

    • In C++: A fixed repertoire, but overloadable

Reference

C++ adds three new operators ( .*, ->*, ::) of which the scope operator :: is the most important

( .* and ->* are special operators that binds pointer to members to a particular object)

Reference

Control structures
Slide Contents Index
References 

The control structures in C are well-known - and almost identical - to control structures in other languages in the C family

  • Selection

    • if conditional and if-else

    • switch - with the break issue!

  • Iteration

    • while and do-while

    • for

      • C++: Can declare local variables (of one type) in the initialization part (not possile in ANSI C)

      • C++: Range-for (called foreach in similar languages)

  • Ohter control mechanisms in C

    • goto, break, continue

    • Blocks: {...}

Program: A program with a for loop in C.
#include <stdio.h>

int main(void){

  int i = 55, j = 77;

  printf("i = %d, j = %d\n\n", i, j);

  for(j = 10, i = 0; i < 5; i++, j++){
    printf("i = %d, j = %d\n", i, j);
  }
  printf("\n");

  printf("i = %d, j = %d\n", i, j);

  return 0;
}

Program: Program output.
i = 55, j = 77

i = 0, j = 10
i = 1, j = 11
i = 2, j = 12
i = 3, j = 13
i = 4, j = 14

i = 5, j = 15

Program: Illustration of local variables in a for loop in C++.
#include <iostream>

using namespace std;

int main(){

  int i = 55, j = 77;

  cout << i << "  " << j << endl << endl;

  for(int j = 10, i = 0; i < 5; i++, j++){
    cout << i << "  " << j << endl;
  }
  cout << endl;

  cout << i << "  " << j << endl << endl;
}

Program: Program output.
55  77

0  10
1  11
2  12
3  13
4  14

55  77

Functions and parameters
Slide Contents Index
References 

Non-nestable functions

Parameters are value parameters - Call-by-value

  • Function basics

    • Named, statically typed

    • Void (returns nothing) or with a single return type

    • Functions cannot be nested in each other in ANSI C - C89

      • A non-standard gcc extension allows such nesting, however.

  • Parameters

    • Parameters are passed by value

      • Pointers passed as value parameter: "Call-by-reference"

    • Positional correspondence

    • There exists an "ugly" variable length parameter mechanism

      • Unspecified number of arguments: int printf(const char* ...)

  • From C to C++

    • Overloaded functions: Several functions with the same name

    • Default arguments: Trailing parameters can be given default values in the formal parameter list

    • int f() in C++ corresponds to int f(void) in C

    • Lambda expressions in C++11

Call-by-reference parameters via pointers
Slide Contents Index
References 

A call-by-reference parameter in C is a pointer passed as a call-by-value parameter

  • Motivation

    • Output parameters

    • Input parameters: Avoid copying large data structures

  • Examples

    • The struct functions discussed earlier

Reference

Program: A C program with a swap function.
#include <stdio.h>

void swap_doubles_ptr(double *d1, double *d2){
  double temp;
  temp = *d1;
  *d1 = *d2;
  *d2 = temp;
}

int main(void) {
  double e, f;

  e = 5.0, f = 7.0;
  printf("%f %f\n", e, f);    // 5.0 7.0
  swap_doubles_ptr(&e, &f);  
  printf("%f %f\n", e, f);    // 7.0 5.0
  
  return 0;
}

Program: C++ Preview: A similar C++ program with a swap function - uses references.
#include <iostream>
using namespace std;

void swap_doubles_references(double &d1, double &d2){
  double temp;
  temp = d1;
  d1 = d2;
  d2 = temp;
}

int main(){
  double e, f;

  e = 5.0, f = 7.0;
  cout << e << " " << f << endl;   // 5 7
  swap_doubles_references(e, f);  
  cout << e << " " << f << endl;   // 7 5

  return 0;
}

C++ offers a reference type that establishes an alias to an existing location in memory

Memory Allocation
Slide Contents Index
References 

Two functions for allocation of memory from the heap

A function for deallocation of the memory

From <stdlib.h>

  • Allocation functions

    • malloc(size)

    • calloc(number_of_objects, size_of_object)

    • These functions return a null pointer in case of problems

  • Reallocation - resizing of allocated object

    • realloc(ptr, newsize)

  • Deallocation

    • free(ptr)

In C++ the new and delete functions are used instead of malloc, calloc and free

Exercise 1.6. Dynamic allocation of persons and addresses

This is a continuation of an earlier exercise about structs (and pointer to structs).

We have on an earlier slides discussed struct person and struct address. More specifically, struct address appear as the location field in struct person.

Write a version of the program that allocates both persons and addresses dynamically. A person 'object' have a pointer to an address 'object'. And the rest of the program should operate on person pointers and address pointers instead on structs with value semantics.

C Program organization
Slide Contents Index
References 

  • Physical program organization

    • Header files and C files

    • .h and .c files

    • Textual inclusion via the preprocessor language

  • Logical program organization

    • Relatively weak and primitive support

    • Almost nothing

C++ takes over C's physical program organization and expands on logical program organization (via support of namespaces).

The standard library
Slide Contents Index
References 

C comes with a relatively small standard library

  • IO is dealt with by <stdio.h>

    • printf and scanf

    • FILE and file functions

  • Standard lib <stdlib.h>

    • Conversion functions, random number functions, ...

    • malloc, calloc, free

  • String functions <string.h>

    • strlen, strcpy, ...

  • Character class test <ctype.h>

    • isalpha, isdigit, ...

  • Mathematical functions <math.h>

  • Constants for upper and lower limits - integer types <limits.h>

  • Constants for upper and lower limits - floating point types <float.h>

  • Date and time functions <time.h>

  • Variable argument lists <stdarg.h>

  • And more: <assert.h>, <ctype.h>, <errno.h>, <locale.h>, <setjmp.h>, <signal.h>, and <stddef.h>.

Most standard libraries C some_lib.h can be used in C++ under the name csome_lib

Reference
  • The C++ Prog. Lang. (4. edition): Page 863


C/C++ Compatibility

C/C++ Compatibility
Slide Contents Index
References 

Quotes from The C++ Prog. Lang. (3. edition):

With minor exceptions, C++ is a superset of C (meaning C89)

Well-written C programs tend to be C++ programs as well

Reference
  • The C++ Prog. Lang. (3. edition): Page 816

Reference
  • The C++ Prog. Lang. (4. edition): Page 1271

  • Keywords

    • Many new keywords in C++ relative to C

    • Such keywords may be used as identifiers in some C programs

  • A number of small differences

    • Almost all of these represent poor style if they appear in C programs

    • Selected small differences at the next slide

Appendex B.2 in The C++ Prog. Lang. (3. edition) deals with this topic

In The C++ Prog. Lang. (4. edition) see section 44.3

C/C++ Compatibility - some small details
Slide Contents Index
References 

Most of details mentioned below do not appear in everyday C programs

Reference
  • The C++ Prog. Lang. (3. edition): Page 816

Reference
  • The C++ Prog. Lang. (4. edition): Page 1271

  • Comments

    • // comments are supported in C++ and C99, but not in ANSI C (C89)

  • Functions without argument types

    • Legal in C - but poor style in C. Not legal i C++.

  • A type is int if not specified

    • Possible in C, but poor style. Not legal i C++

  • 'Inline' structs in return type and in parameter lists

    • Possible in C. Not legal i C++.

  • Enumeration types

    • In C a variable of enumeration type can be assigned to an integer.

    • Not possible in C++.

  • Multiple definitions at global level

    • Global data definitions may be repeated in C. Not in C++.

  • Pointers to void

    • may in C be assigned to variables of any pointer type. Not in C++.

  • Static

    • In the meaning of 'local to translation unit' is deprecated in C++.

  • Casts

    • C-style casts should have been decrepated...

    • C++ has other means for casting.

Examples appear in appendix B.2 in The C++ Prog. Lang. (3. edition)


Collected references
Contents Index
Goals for the first submission
The C++ Prog. Lang. (3. edition): Sample reference: Introduction. Page 1
The C++ Prog. Lang. (4. edition): Sample reference: Introduction. Page 1
The Tiobe Index
Function objects
Lambda expressions
The C++ Prog. Lang. (4. edition): enum class. Page 50
Effective Modern C++: Prefer scoped enums to unscoped enums. Item 10
The C++ Prog. Lang. (4. edition): Type aliases. Page 167
Effective Modern C++: Prefer alias declarations to typedefs. Item 9
Operator overloading
Pointer to members
Structs and functions
The C++ Prog. Lang. (4. edition): Page 863
The C++ Prog. Lang. (3. edition): Page 816
The C++ Prog. Lang. (4. edition): Page 1271

 

Chapter 1: From C to C++
Course home     Author home     About producing this web     Previous lecture (top)     Next lecture (top)     Previous lecture (bund)     Next lecture (bund)     
Generated: August 1, 2017, 13:24:46