C++ to C quick-reference

While our first-year courses (160/161) are primarily taught in C++, many students will soon find themselves working in C as well. This guide is meant to highlight the key things you'll need to learn to move from C++ to C.

These topics are in no particular order whatsoever.


Compilers and file extensions for C

OK, this may be a smidge on the obvious side, but different programming language implies different compilers and different file extensions.

C source code files generally use the extension .c, rather than C++ extensions such as .cpp, .cc, .cxx, .C, etc.

There are a wide variety of C compilers for various platforms (just as there are a wide variety of C++ compilers). While we use g++ as our C++ compiler, we use gcc as our C compiler.

While most things with respect to compilation will be the same as with C++, you may encounter some differences in the options/flags used. Examples may include things like explicitly adding the -lm flag to compile programs that use the math library (e.g. gcc myprog.c -o myprog -lm).


There are no classes in C

This means you can't create them and can't use them, everything is done using stand-alone functions and parameters.

This means that instead of having a method acting on a variable (e.g. mystr.length()) you have to pass the variable as a parameter to a standalone function (e.g. length(mystr)).

It also means that if you want encapsulation of code, nice modularity, etc then you'll need to come up with appropriate interfaces via .h files and make sure you adhere to those interfaces to manipulate any data.

You need to be more careful with your style and programming habits, especially in team projects, since it is easier to shoot yourself in the foot if you get sloppy.

This also means that the nice classes supplied in the C++ standard template library cannot be used in C. This includes (but isn't limited to) the following

algorithm   iomanip   list      queue      strstream
bitset      ios       locale    set        typeinfo
complex     iosfwd    map       sstream    utility
deque       iostream  memory    stack      valarray
exception   istream   new       stdexcept  vector
fstream     iterator  numeric   streambuf
functional  limits    ostream   string

Including libraries in C

C++ uses many of the standard C libraries, it includes them using the format #include <libraryname>, e.g. <cstdlib>.

C, on the other hand, uses the exact filename of the header file to be included, e.g. <stdlib.h>.

The list below identifies a handful of the libraries shared between the two languages, and the different headers for each

   C++              C
cassert             assert.h
cctype              ctype.h
cerrno              cerrno.h
cfloat              float.h
climits             limits.h
clocale             locale.h
cmath               math.h
csignal             signal.h
cstdarg             stdarg.h
cstddef             stddef.h
cstdio              stdio.h
cstdlib             stdlib.h
cstring             string.h
ctime               time.h
cwchar, cwctype     wchar.h, wctype.h

No bool, namespaces, or operator overloading in C

While const is now supported in C, this was not always the case. Instead programmers often relied on the #define macro (which does text substitution prior to compiling). Here are a quick couple of examples
const char c = 'c';             #define c 'c'
const int  i = 33;              #define i 33

bool, true, and false are not a part of the C language, but it can be simulated with typedefs, enumerated types, or #defines. There is also a library, stdbool.h, which can be included and which defines bool, true, and false.

Operator overloading is not supported in C (that comes as a part of C++ classes), so don't bother trying ;-)

Namespaces are also not supported in C.


printf/scanf instead of cin/cout

Since the iostream (and similar) libraries aren't usable in C, one must use the stdio.h library instead.

In terms of basic I/O this means using printf and scanf instead of cout and cin, respectively, and performing file I/O with fprintf and fscanf.

Output
printf is a function whose first parameter is the text we want to print, and whose remaining parameters (if any) are values we want to embed within the text.

We put markers, or placeholders, within the text to indicate exactly where we want the values to go, and use different types of markers to indicate what kind of data value is expected.

For example, the marker for an integer is %d, and the marker for a float is %f. The snippet below shows us embedding two floats and an int within a string of text.

int x = 1;
float f = 1.1;
float g = 2.5;
printf("one int: %d, a float %f, another %f", x, f, g);
The commonly used placeholders are
%d   decimal (integers)
%f   real numbers (in fixed point format)
%e   real numbers (in scientific notation)
%c   character
%s   a text string, e.g  "blah blah blah"

There are also a variety of formatting options that can be specified in the placeholder, between the % and the key letter.

For example %4.2f specifies the float is to be padded to 4 characters total with, with 2 digits shown after the decimal point.

Input
Keyboard input is performed with scanf, which takes parameters much like printf: the first one is a text string with a placeholder for the type of data to be read, the second parameter is the address of the variable to hold the value read in.

For example, to read a single integer:

int i;
scanf("%d", &i);  /* remember the & before the variable! */
scanf returns an int, specifying how many items it succeeded in reading (0 if it can't read anything that fits the specified format). Thus if we wanted to read an unknown number of ints and print them as we go, we could use
while (scanf("%d", &i) > 0) {
   printf("%d\n", i);
}
Other input options are %s for string, %x for hexadecimal, %f for fixed-point float, %e for exponential notation, %g will accept either fixed or exp notation, %c for char, %d for decimal, %o for octal, %p for pointer, etc.

If you add a * between the % and the input type specifier it means the item read is discarded instead of stored to a variable. For example, the following reads three ints but discards the middle one:
scanf("%d %*d %d", &i, &j);

You can (and probably should) specify the maximum number of characters to be read into the target variable, e.g. "%10s" indicates a maximum of 10 characters.

You can also extract data from patterns of input. For example, to read and extract three ints from input of the form (ddd) ddd-dddd you put the non-whitespace characters that are part of the pattern to discard (i.e. the brackets and dash) into the format string:
int i1, i2, i3;
scanf("(%3d) %3d-%4d", &i1, &i2, &i3);

Single-character input, capturing whitespace
You can also use getc() to read a single character, e.g.
char c = getc();

Reading data to/from text strings (char[])
You can use sscanf and sprintf to read data to/from character arrays. The approach is the same as scanf/printf, but you specify the character array as a first parameter, e.g.
int i; // int to translate into text
char text[80];
sscanf(text, "%d", &i);


File I/O in C

As with regular I/O, file I/O must be handled differently in C.

While the basic concepts (open the file in a specific mode, read from/write to it, close the file) are the same, the specific functions used are different.

Opening the file is done with
FILE *fp = fopen("filename", "r"); /* for read mode*/
The modes are r, w, a for read, write, append.

The reading and writing are handled through fprintf and fscanf. These correspond to printf and scanf except that they include a file specifier before the text string, e.g.
fprintf(fp, "blah blah %d", someInt);

There is also a routine, fgets, that allows you to read a line of text into a character array.
fgets(textArr, MaxLen, fp);

Finally, you can use fgetc(fp) to read a single character or fputc(c, fp) to write a single character.

Closing the file is done with fclose(fp)


Pointers instead of reference parameters

Reference parameters are not a part of the C language.

The practical alternative is to pass a pointer to the item you want the function to modify, then dereference the pointer within the function.

For example, suppose I want to write a function to swap two ints:
/* function to swap the value of the variable
 *    that xPtr references with the value of 
 *    the variable that yPtr references
 */
void swap(int* xPtr, int *yPtr)
{
    int temp = *xPtr;
    *xPtr = *yPtr;
    *yPtr = temp;
}

/* example calling the function with the addresses of x and y */
int main()
{
    int x = 3;
    int y = 4;
    swap(&x, &y);
}


malloc/free instead of new/delete

new and delete are not usable in C, instead we use the malloc (or calloc) and free routines.

Malloc needs one parameter - the number of bytes of memory which need to be allocated.

The sizeof function tells us how much space is used by a single data TYPE, e.g. sizeof(int) tells us how much space is used by an int.

If we are allocating one item of a data type we can just use the sizeof value, whereas if we are allocating an array then we need to multiply the size by how many items we need, e.g. for an array of 40 ints we would call malloc(40*sizeof(int)).

Unfortunately, malloc's return value is 'void*', which basically means a pointer of no particular type.

When we assign this to our actual pointer variable, we need to identify what kind of pointer we should treat malloc's returned value as. (There has GOT to be a better way to phrase that.)

free(ptr) releases the space when we're done with it.

The example below shows us dynamically allocating, initializing, and then deleting an array of 40 ints
int *myArray;
myArray = (int*)malloc(40*sizeof(int));
int i;
for (i = 0; i < 40; i++) {
   myArray[i] = 0;
}
free(myArray);


Strings as null-terminated char arrays

Since the string class isn't usable in C, text handling is instead done using null-terminated character arrays, usually with some support from the string.h library.

If we populate a char array with text, we can include the null character ('\0') to mark the end of the part of the array we are using.

E.g. if I have an array of 40 characters to hold a name, and choose to store the name "Fred" in the array, I should put something after the 'd' to indicate the rest of the array isn't currently in use.
char name[40];
name[0] = 'F';
name[1] = 'r';
name[2] = 'e';
name[3] = 'd';
name[4] = '\0';
This convention is used across most forms of text manipulation in C, but means we need to be careful when creating/using text functions - remember to test for/include the '\0' at the end of 'strings'.

For example, the function below could be used to copy one 'string' into another
/* assumes destination has space for maxSize+1 chars */
int  copyAstring(char source[], char destination[], int maxSize)
{
   int i = 0;
   /* copy from the source to the destination, one char at
    * a time, until you've copied the max number of chars
    * or you've hit the null terminator in the source
    */
   while ((i < maxSize) && (source[i] != '\0')) {
      destination[i] = source[i];
      i++;
   }
   /* put the null terminator in the destination and 
    * return the number of characters written (prior
    * to the null terminator)
    */
   destination[i] = '\0';
   return(i);
}

Many routines are available in the library to help in this, be sure to check them out in any reference manual.

strlen
strcpy, strncpy
strcat, strncat
strcmp, strncmp
strchr, strstr, strtok, etc