Null Pointers

Within the medium and compact models, code pointers and data pointers differ in size: one is 16 bits wide and the other is 32 bits wide. When using these memory models, you should be careful in your use of the manifest constant NULL.

NULL represents a null data pointer. The library include files define it as follows for C:

#define NULL ((void *) 0)

For C++, it is defined as follows:

#define NULL 0

Summary: There can be problems in models with different sizes of code and data pointers.

In memory models where data pointers have the same size as code pointers, the actual size of a null pointer doesn't matter. In memory models where code and data pointers are different sizes, problems can occur. Consider this example:

void main()

{

func1( NULL );

func2( NULL );

}

int func1( char *dp )

{

.

.

.

}

int func2( char (*fp)( void ) )

{

.

.

.

}

In the absence of function prototypes for func1 and func2, the compiler always assumes that NULL refers to data and not code.

The example above works correctly in tiny, small, large, and huge models because, in those models, a data pointer is the same size as a code pointer. Under medium or compact model, however, main passes NULL to func2 as a null data pointer rather than as a null code pointer (a pointer to a function), which means the pointer is the wrong size.

To ensure that your code works properly in all models, declare each function with a prototype. For example, before main, include these two lines:

int func1( char *dp );

int func2( char (*fp)( void ));

If you add these prototypes to the example, the code works properly in all memory models. Prototypes force the compiler to coerce code pointers to the correct size. Prototypes also enable strong type-checking of parameters.