Legacy Code

During its 30-year existence, C has changed considerably. Yet many

organizations, classic algorithm books, and legacy open source

libraries maintain pre-standard C code. Up-to-date compilers including

GCC 2.96 and others will refuse to accept such code as is though. This

week, I will explain how to fit legacy C code to modern compilation

environments with minimal changes.

Old-Style Function Declarations

In preliminary stages of C, function declarations looked as follows:

int func() /*no parameters inside parentheses*/

int a,b; /*instead, parameters were declared here*/

float f; /*another parameter*/

{

/*...function body*/

}

Old-style function declaration always had empty parentheses. The

parameters were declared after the parentheses and before the opening

brace of the function body. Today, this function would look like this:

int func(int a, int b, float f)

{

/*...function body*/

}

For many years, C supported the old-style declarations, but not

anymore. If you intend to use legacy C code containing old-style

function declarations, then change them as shown above.

Defaulting to int

In pre-standard C and C++, the default type of incomplete declarations

used to be int. Thus, the following declarations:

static x;

unsigned y;

f();

main() {}

Would be construed as:

static int x;

unsigned int y;

int f();

int main() {}

Both C and C++ banned this "defaulting to int" convention several years

ago. If your legacy code contains such incomplete declarations, then

state the missing int explicitly.

Using char* as a generic pointer

Before the type void* was introduced to C and C++, char pointers were

used as generic pointers. Thus, the implied return value of standard

functions such as malloc() used to be char*, not void* . Likewise,

linked lists and other pointer-based containers would use char* instead

of void*. This practice compromises type-safety and might mislead the

human reader into thinking the code handles strings. Here again, you

want to change all the occurrences of char* to void* unless they indeed

refer to strings.

Compiled libraries

Sometimes, the original source files become unavailable; only a

compiled library file and a collection of header files containing

declarations of functions and data structure are available. If you wish

to use any of the library's functions, then you can change the

original, old-style header file declarations as shown above. Copying

only the declarations you need without including the original header

files (in many cases, you only need a handful of functions of a library

containing hundreds of functions) presents a simpler solution though.

Then fit those declarations to ANSI-style function declarations. For

example:

/* func is a legacy library function.

declaration was copied from original header file and changed*/

void func(int n);

int main()

{

...

}

Make sure that the library is specified in the "ld" command.

Insider: How the basic tech behind the Internet works
Join the discussion
Be the first to comment on this article. Our Commenting Policies