Reading numbers from a file

To read numbers from a file into a variable, there are two basic alternatives:

  • in a text file each byte, or char in the file represents one digit. In this case, the function fscanf can be used with an appropriate format string.
  • in a binary file the numbers are represented either in big or little endian order just as they are in memory. In this case, we need to know which endianness is used both in the file and in memory. If they are the same, we can simply use the function fread to read binary data, otherwise, we have to make a conversion after the call to fread.

See the book for details about these functions!

(I will add example code here soon…)

New edition available at Amazon

The second edition of the book is now available at the Amazon sites. This edition has additional material on the C keyword restrict, Unix signals, and compiler flags for generating code for runtime checks to detect some cases of undefined behavior, including memory errors and signed integer overflow.There are also various other changes such as removing most of the text about the API for programming the Cell processor. Most of the book is unchanged.

Using addresses as keys in AVL trees or other data structures

Suppose you wish to store objects in a set, and you are concerned with

  • whether the object already is in the set, and
  • you want to be able to iterate through all objects in the set,

but that you don’t need to look up objects using a special key. You then probably will use a comparison function which works like strcmp to compare your objects.

The simplest thing is to use the address of the object. What can go wrong with that?

Depending on the rest of your program, it may no longer be deterministic. For authors of optimizing compilers, that is a very bad feature! You want your code to be deterministic so that you can easily re-create a bug. If your program is linked dynamically, then you don’t have control over which implementation of malloc and free is used on an unknown machine in the future, and therefore the address assigned to your objects can be different from when you tested your code — and you may no longer be able to reproduce a nasty bug so easily. So use something else, such as a integer for this purpose.

But, if you still want to use addresses as keys, how should then the comparison function look?

What is wrong with the following failed attempt?

int compare_address(const void* ap, const void* bp)
        return ap - bp;

There are several problems.

  • Pointer arithmetic on void pointers is not permitted by the C standard.
  • If we cast the pointers to e.g. char pointers, the code may trigger undefined behavior. The standard only allows pointers to the same array object to be subtracted (counting a scalar as an array of one element). If our objects were allocated with malloc, one at a time, it would be invalid C to subtract their addresses.
  • Subtracting two pointers produces a result with the implementation defined type ptrdiff_t which can be an int also on a 64-bit architecture. If the pointer difference cannot be represented, we have undefined behavior due to overflow.
  • Even if ptrdiff_t is large enough to hold the result, it might not fit the return type which is int. The result of that is implementation defined but certainly a bug since even if the difference is negative, the return value can be positive due to the truncation.
  • How should we do it then? What about this?

    int compare_address(const void* ap, const void* bp)
            const char*     a = ap;
            const char*     b = bp;
            if (a < b)
                    return -1;
            else if (a > b)
                    return +1;
                    return 0;

    This is also wrong because we are not allowed to compare addresses using the relational operators (equality operators are OK) unless they refer to elements of the same array, just like with subtraction.

    We can do like this however:

    #include <stdint.h>
    int compare_address(const void* ap, const void* bp)
            uintptr_t       a = (uintptr_t)ap;
            uintptr_t       b = (uintptr_t)bp;
            if (a < b)
                    return -1;
            else if (a > b)
                    return +1;
                    return 0;

    The type uintptr_t is an integer type sufficiently large to hold the value of a pointer.

Polynomial multiplication

This is is the first C programming challenge on the site and is about writing memory efficient C code.

  • Download the source code for polynomial multiplication here.
  • First implement the missing functions declared in poly.h and type make. The correctness of your code for the sample input will then be checked using diff.
  • Then try to make your code as memory efficient as possible for a 32-bit Power computer. The memory size is counted as static memory used by poly.o i.e. excluding stack and heap memory but you need to use the heap since the tested input will have arbitrary size at the grading server. Memory leaks are detected and forbidden. You are only allowed to use at most 4 times as much heap memory as my reference implementation for the random input tested at the server. The maximum stack size is reduced by the grader before running your program.
  • Mail your poly.c solution to with subject line: assignment poly by username where username is alphanumeric (with dot and underscore allowed). No registration is required and everyone is welcome to submit solutions.
  • If your code passes the tests, you will get a score back (in the reply mail subject line as well as in a file).
  • The high score list with the 10 best scores is here.
  • My (i.e. Jonas’) submission is a relatively straight forward reference implementation (username ref and domain with 735 bytes — can you beat that? 🙂

Reading a number

In C 'A' is an int constant used to represent the character ‘A’. The same is true for digits, of course.

If you have a variable c which contains a digit (say ‘9’) you can find the numerical value by c - '0' which in this case evaluates to 9.

If you wish to read a number (such as 124) from input using getchar(), you can do as follows. First check that the current input char you have read is a digit. Do that with the function isdigit. It returns a nonzero value if you give it a digit, such as '0' or '9'. To read a number then, you can have a variable x initially set to zero, and do:

x = x * 10 + c - '0';

Do this for each input char c you read that is a digit. If we read the digits '1', '2', and '4' in sequence, x will first be 0, then 1, then 12, and finally 124!

Note that the type of c should be int, as explained here.

Input and getchar

The most basic function to read input in C is int getchar(void). Obviously, it reads one char. What might not be obvious (at least not initially) is that we should not save the returned value in a variable of type char. Instead, do as follows:

int c;
c = getchar();

Suppose you wish to read all input and use getchar() in a loop. When all input has been read, the return value from getchar() is the special value EOF which is an integer value that is guaranteed to be different from the character set used (such as ASCII). EOF stands for enf of file and its value can be -1 for instance.


while ((c = getchar()) != EOF) {


Will end up in an infinite loop if the variable c has an unsigned integer type, such as unsigned char. In C we have three distinct char types:

  • signed char,
  • unsigned char, and
  • char
  • .

The last of these is either signed or unsigned and which it is is implementation defined (decided by the compiler). If it is unsigned, then c will never be equal to EOF and the loop will not terminate.

Therefore, it is best to declare c as above with type int. For the assignments in the book with downloadable files, we explicitly tell the compiler that we want char to be unsigned in order to test your code for this trap.

New assignments added: RPN, Endian, and Word

The first three assignments have now been added to the downloadable source code page. You will find detailed specifications of the assignments in the book shortly. If you have a previous printing of the book, or look here, you can start with the RPN assignment right away (the specifications for the assignment have become stricter, but you can figure them out based on the file correct in the zip-file.