C Differences

C vs C++

We've covered quite a few topics in these first few weeks. It's time to pause and discuss some of the differences between what we've learned with C++ and how the C language differs. Many of these differences are quite small, so you just need to be aware of them and remember which to use depending on the language that you are utilizing. Other differences are bigger, but since this is an introductory course, we won't actually get to the more advanced topics that really illustrate why we have the two languages instead of just one.

To keep things simple, we'll cover what we've learned so far and how it differs.

Libraries, Compilers, and Headers

Compiling a C program will use the gcc compiler instead of g++ (because C++ is a superset of C, g++ will actually work, but won't constrain you to C-only conventions...and you need to be aware of those constraints). Just like g++, you'll notice it creates an executable called a.out, which you run to run the program.

The next difference is simple file name conventions. A file of C code should be named code.c in contrast to our C++ code.cpp extension. It's a simple difference and is not actually required, but this is the convention to follow to make sure you don't confuse what language is in your file. Let's take a look at a simple C and C++ program now.

file.cppfile.c

#include <iostream>
using namespace std;

int main() {
  return 0;
}

#include <stdio.h>


int main() {
  return 0;
}
g++ file.cppgcc file.c

You should notice that the included library is different. In order to have basic input/output functions for C, you now include stdio.h instead of iostream. You cannot include iostream because that library is written with C++ and won't compile with your gcc compiler. The other difference is that we've lost the std namespace.

Variables and Printing

Printing is different in C because the shorthand operators like >> are not available and neither are the handy variables cin and cout. Those are handy things we get from C++ and its available libraries. Let's continue our example and print a greeting:


#include <iostream>
using namespace std;

int main() {
  cout << "Hello world!" << endl;
  return 0;
}

#include <stdio.h>

                            
int main() {
  printf("Hello world!\n");                           
  return 0;
}

The new function is printf and it can take a single string argument. This is then printed the terminal. Notice that endl is no longer available, so you use must explicitly use the newline char '\n' when you want a new line.

What about variables? The good news is that C and C++ have roughly the same primitive types so not much changes there. The one difference is that bool is not a variable type in C. There are no true/false constant values and there is no bool type. Instead, the int value 0 corresponds to false and all other values true.

Let's put these differences together and print out some numbers:


#include <iostream>
using namespace std;

int main() {
  int n = 20;
  double d = 4.5;
  cout << "I bought " << n << " apples for $" << d;
  return 0;
}

#include <stdio.h>

                            
int main() {
  int n = 20;
  double d = 4.5;
  printf("I bought %d apples for $%f", n, d);
  return 0;
}

The C printf function can take any number of arguments, and the first argument must be a string which is the template for what you print. If you want to print variable values, then you must use format specifiers like %d and %f in my example. Specifiers tell the program how to display the values amongst the rest of the string. All the format specifiers can be seen here - as you can see, d is for "decimal integers" (decimal, as opposed to octal, or hexadecimal, rather than because it has a decimal point - it doesn't, because it's an integer). If you replace %d with %o, then you'll get 11 in octal (which is 13), while if you replace it with %x, you'll get 11 in hex (which is b). If you replace it with %f, you'll get a compilation error, because integers aren't floats (that is, numbers with an actual decimal point in them).

Loops and Conditionals

What about while, do-while, for loops, and if statements? It's all the same. Here's a loop comparison. There is no difference except for how we print:


#include <iostream>
using namespace std;

int main() {
  for( int i = 0; i < 5; i++ )
    cout << "Hello for the " << i << "th time!" << endl;
  return 0;
}

#include <stdio.h>

                            
int main() {
  for( int i = 0; i < 5; i = i+1 )
    printf("Hello for the %dth time!\n", i);
  return 0;
}

Input (Pointers)

Input is one of the bigger differences between the languages. The next thing we'd like to do is read values in from the user, cin-style. To do this in C, though, we need to see for the first time, a Very Big Idea in programming - pointers. We are going to spend a LOT of time on pointers, but for now, let's keep them as simple as possible.

Variables store information in a particular memory location. Every memory location is numbered, usually using hex. We can see that location by using the & operator. Compile and run the following C++ program:

#include <iostream>
using namespace std;

int main() {
  int a = 3;
  cout << a << ' ' << &a << endl;

  return 0;
}

In that program, when the cout command runs, you first see the value of a (3), and then see the location of a. I have no way of predicting what that location will print out, since each of your operating systems will do things a little differently, but I know you'll get a large hex number out there. It turns out we can store memory locations in a variable of their own, called pointers.

#include <iostream>
using namespace std;

int main() {
  int a = 3;        //The variable
  int* ptrToA = &a; //The pointer
  cout << a << ' ' << &a << ' ' << ptrToA << endl;

  return 0;
}

The * in the declaration means ptrToA is a pointer - the int* means when you go to the stored value, you'll find an int - so, ptrToA is a pointer to an integer. This is going to be a powerful, powerful tool, but for now, we're just going to use it to read things in from the user.

Input

If you think about the C++ statement cin >> x, what that actually means is "take the value off the text stream, and store it in the location used by x". C++ uses some fairly complex stuff (called pass-by-reference) to make this happen that we're not ready to appreciate yet, but it's a feature that C doesn't have. So in C, we have to explicitly say, "read in a value, and store it in this location, indicated by this pointer." We do this using the scanf function:

#include <stdio.h>

int main() {
  int x = 0;
  int* ptrToX = &x;
  printf("Please enter an integer: ");
  scanf("%d", ptrToX);

  printf("x is now %d\n", x);

  return 0;
}

Go ahead and compile and run that program, to see that indeed, an input integer reads in to x. The scanf line is saying, read in an integer ("%d", as with printf), and store it in the location indicated by ptrToX. ptrToX, of course, points to x. So, when we print out x, we see the value that has been read in.

Like with printf, a single scanf command can read in multiple values, as long as the number of specifiers and number of pointers is the same.

scanf can do some other cool things, too. Suppose you want the user to type in a command like Convert ___ dollars. and you want to burn the "Convert" and the "dollars." You can do that this way:

#include <stdio.h>

int main() {
  double money = 0;
  double* moneyPtr = &money;
  scanf("Convert %lf dollars.", moneyPtr); // Consumes "Convert" then reads the double into the
                                           // memory location indicated by moneyPtr, then consume "dollars."
  printf("Converting %f dollars...\n", money);

  return 0;
}

As a final note, scanf is somewhat constraining in that the input has to be formatted exactly like you specify in your string argument. This means you don't have flexibility for the user to type anything different, such as lowercase where uppercase was expected. "Convert" in the scanf above cannot be "Change" or "convert". Whitespace has some flexibility, though, and any space character you have in your scanf string is interpreted as "one or more spaces". This means the user can have extra spaces by accident and your input will still work. We'll talk later about strings and how to have more flexibility once we learn about arrays in the next weeks.

Problems

  1. Write a C program solution for HW 6:
    $ ./sleeping
    Time: 0330
    Go away, I'm asleep!
    $ ./sleeping
    Time: 1650
    I'm Awake!
    $ ./sleeping
    Time: 2301
    Go away, I'm asleep!
       
  2. Write a C program solution for HW problem 2:
    $ ./product
    Enter two integers: 2 5
    Product of all integers between 2 and 5 is 120
    $ ./product
    Enter n: 10 13 
    Product of all integers between 10 and 13 is 17160
    $ ./product
    Enter n: 1 12 
    The product of all integers between 1 and 12 is 479001600