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.

Top 10 Hot Internet of Things Startups
Join the discussion
Be the first to comment on this article. Our Commenting Policies