Moving from C to C++

"The C Programming Language: A new language which combines the flexibility of assembly language with the power of assembly language." -- Murphy's Introduction to C

Some of the more obvious differences between C and C++:

Comments

In C, we only had block comments. In C++, we also have "to end of line" comments. An example will demonstrate:
int main(void)
{
  /* This is a block comment. Ok in C and C++ */

  /*
   This is also a block comment. Ok in C and C++
   */

  // This is a C++ style comment.
  // This type of comment may not work in all C compilers.
}
The C++-style comments will include everything from the // (which is a single token much like the ++ operator) to the end of the line. So, we will still need the orginal and more flexible /* ... */ comment syntax.
int fn1(int a /* a should be positive */, int b /* b can't be 0 */);
Strictly speaking, the // comment character is illegal in a C program. However, many C compilers have been extended to accept both types of comments. (Microsoft has been accepting it since version 6.0 of the DOS version of C, which is about 1989. Yeah, they started over again at 1.0 with "Visual" C++ and there never was a version 3. But I digress...)

Function Prototypes

In C, if the compiler encountered a function call before seeing the function declaration or definition, it would assume certain things about the function:
void fn2(void)
{
    /* Undeclared function, assumes it takes int,double and returns an int */
  SomeFunction(1, 3.0);
}
In C, the above program will compile "fine". Of course, it won't link. In C++, you will get an error (not a warning):
error: 'SomeFunction' undeclared (first use this function)
You must prototype every function in your program:
// Function prototype required in C++   
int SomeFunction(int, double);
  
void fn2(void)
{
    // Compiles just fine now
  SomeFunction(1, 3.0); 
}

void Parameter Lists

In C, a function is allowed to not specify any parameters in its parameter list:
int foo();
This means that the function can take any number and type of arguments. This was simply because the earliest versions of C didn't require the programmer to declare them. (This turned out to be a disaster and later versions of C "encouraged" function prototypes so the compiler could check for bad behavior.) If a function truly does not take any arguments, then the void keyword is used to indicate this fact:
int foo(void);
Realize that these two functions are NOT the same in C:
Accepts any number/type of argumentsAccepts no arguments
int foo();
int foo(void);
However, in C++, the two functions are the same. The lack of parameters means that the function does not accept any arguments. It's a stylistic issue as to whether or not the void keyword is used. Also, since all functions in C++ must be prototyped before use, it's much more likely that the compiler will detect any misuse.

Printing to stdout

There are more ways to print in C++. Typically: C example:
#include <stdio.h>

int main(void)
{
  printf("C programming ");
  printf("is fun.\n");
  
  return 0;
}
C++ example:
#include <iostream> // Notice the missing .h in the filename

int main()
{
  std::cout << "C++ programming ";
  std::cout << "is more fun." << std::endl;
  
  return 0;
}
We will look at cout (and the input version, cin) in more detail later.

Variable Declarations

In C, all variables must be declared at the top of a scope. In C++, this is relaxed to allow you to declare new variables closer to their actual use.
#include <stdio.h> /* printf */

int main(void)
{
  int a;              /* declaration                               */
  int b = 3;          /* initialization (declaration + assignment) */
  double c = foo(2);  /* initialization (declaration + assignment) */
  int x;              /* OK, declaration                           */

  a = b * 2;          /* assignment/multiply (no declaration)      */

  /* In C, no more declarations allowed in this scope */

  c = 3.1415926;      /* assignment, no declaration                */
  printf("%f\n", c);  /* function call, no declaration             */

  int d = 7;     /* error in C, OK in C++                          */
  int e;         /* error in C, OK in C++                          */

  x = 5 * c;     /* OK, no declaration                             */

  return x;
}

This also allows you the convenience of declaring the index of a for loop precisely where you need it. In C, this is the formal syntax for the for loop:
for ( <expression1>; <expression2>; <expression3> )
  <statement> 
In C++, there is a slight (but important) difference:
for ( <init-statement>; <expression>; <expression> )
  <statement>
This is what allows you to declare the index variable as part of the loop in C++:
int a[10];

/* i doesn't exist here */

for (int i = 0; i < 10; i++)
  a[i] = i;

/* i doesn't exist here */

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

/* i doesn't exist here */
Each of the two i variables are different. (Different scopes)

You have to watch out and not do this:

int a[10];

for (int i = 0; i < 10; i++)
  a[i] = i;

  /* ERROR: i is undefined */
for (i = 0; i < 10; i++)
  a[i] = i * i;
The error message from the GNU C++ compiler:
main.cpp:28: error: name lookup of `i' changed for new ISO `for' scoping
main.cpp:25: error:   using obsolete binding at `i'
Fortunately, most (all?) compilers today will give you an error if you do that, though. The reason the compiler doesn't just say that i is undefined is because this is how C++ used to work. The compiler is just trying to remind you that the behavior of the for statement has changed.

If you want to use the index variable from the for loop outside of the loop, you have to declare it outside of the loop:

int a[10];
int i;

  /* i is in scope */
for (i = 0; i < 10; i++)
  a[i] = i;

  /* i is in scope */
for (i = 0; i < 10; i++)
  a[i] = i * i;

  /* The i on the next line is a new variable that exists only in the loop */
for (int i = 0; i < 5; i++)
  a[i] = i * i;

  /* i (from line 2 above) is in scope with value 10 */
printf("The value of i is %i\n", i);

The literal char data type

In C, the type of a literal char is actually int. In C++, the type is char:

C
printf("sizeof('A') is %lu\n", sizeof('A'));
Output:
sizeof('A') is 4
C++
std::cout << "sizeof('A') is " << sizeof('A') << std::endl;
Output:
sizeof('A') is 1
This only applies to literal characters, i.e., constants in single-quotes. Constants and variables of type char are actually char in both languages:
C
char c;
printf("sizeof(c) is %lu\n", sizeof(c));
Output:
sizeof(c) is 1
C++
char c;
std::cout << "sizeof(c) is " << sizeof(c) << std::endl;
Output:
sizeof(c) is 1

The const keyword

In C, const is not the same kind of constant as in C++, which means that you couldn't use it to specify the size of a static array in C:
const int SIZE = 10; // constant?
int array[SIZE];     // compile error, variable sized array
You have to use the #define preprocessor directive:
#define SIZE 10   // SIZE is an alias for 10
int array[SIZE];  // OK, compiler replaces SIZE with 10
In C++, the first example above works as expected.

There is another subtle difference between C and C++ with respect to the const keyword. In C++, declaring a global variable const gives it internal linkage instead of external linkage. Here's an example:

file1.cfile2.c
#include <stdio.h>

const int foo = 1;
void fn(void);

int main(void)
{
  fn();
  printf("foo is %i\n", foo);
  
  return 0;
}
#include <stdio.h>

const int foo = 2;

void fn(void)
{
  printf("foo is %i\n", foo);
}
Compiling the .c files with a C compiler:
gcc file1.c file2.c
Compiling the .c files with a C++ compiler:
g++ file1.c file2.c
How would you answer the above questions now?

The real power of this feature is that you can put constants in header files in C++. This is something that can't be done in C (due to the One Definition Rule), which is why we were always using #define instead of const.

The bool Type

Here is a way we could "add" a boolean type to C:
/* Define our own boolean type and values */
#define BOOL int
#define FALSE 0
#define TRUE  1

BOOL BitIsSet(int value, int position)
{
  if (value & (1 << position))
    return  TRUE;
  else
    return FALSE;
}

void f(void)
{
  BOOL b = BitIsSet(7, 2); /* b is a BOOL                              */
  int x = BitIsSet(7, 2);  /* OK, no type-checking error (BOOL is int) */
  BOOL c = 42;             /* OK, no type-checking error (BOOL is int) */

    /* BOOL is just an int, so the expression evaluates to an integer */
  if (BitIsSet(7, 2))
    printf("Bit 2 of integer 7 is set\n");

    /* Prints: b is 1, c is 42, x is 1 */
  printf("b is %i, c is %i, x is %i\n", b, c, x);
}
In C++, we have a built-in bool type (and true/false):
bool BitIsSet(int value, int position)
{
  if (value & (1 << position))
    return  true;
  else
    return false;
}

void f(void)
{
  bool b = BitIsSet(7, 2); // b is a real bool             
  int x = BitIsSet(7, 2);  // OK, converting bool to int  
  bool c = 42;             // Possible warning: truncating
                           //   int to bool (c is true, 1 as int)       

    // Expression evaluates to a bool
  if (BitIsSet(7, 2))
    printf("Bit 2 of integer 7 is set\n");

    // Prints: b is 1, c is 1, x is 1
  printf("b is %i, c is %i, x is %i\n", b, c, x);
}
There are some obvious issues here:

The Definition of NULL

In C, NULL is a void pointer and is usually defined as:
#define NULL ((void *)0)
In C++, NULL is an integer and is defined as:
#define NULL 0
These two definitions are not the same (integer vs. void pointer) and, depending on the circumstances, may cause compiler warnings or strange behavior.

With most compilers' header files, you'll see something like this (from stdio.h):

/* Define NULL pointer value */

#ifndef NULL
#ifdef  __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif
In practice, this is generally not a problem.

The C++11 specification provides a new keyword, nullptr, that can be used to unambiguously refer to the NULL pointer, however it may be represented. We will look at this later.

Structure tags

Recall the general form of a structure declaration:
struct tag
{ 
  members 
}variable-list;
In C, when we created an instance of a structure, we were required to use the struct keyword: Create a structure named TIME, (no space is allocated):
struct TIME 
{
  int hours;
  int minutes;
  int seconds;
};
Create two variables of type struct TIME, (space is allocated):
struct TIME t1, t2; /* You need the struct keyword in C*/
We could use the typedef keyword:
typedef struct  /* use typedef keyword to create a new type */
{
  int hours;
  int minutes;
  int seconds;
}TIME;            /* TIME is a type, not a variable    */

TIME t1, t2;      /* Don't need the struct keyword now */
In C++, when you define a structure with the struct keyword, you are creating a new type:
struct TIME 
{
  int hours;
  int minutes;
  int seconds;
};
TIME t1, t2;      // TIME is a new type, so you don't need the struct keyword