Pointer Conversions

Passing near or far pointers as arguments to functions can cause automatic conversions in the size of the pointer argument. Passing a pointer to an unprototyped function forces the pointer size to the larger of the following two sizes:

The default pointer size for that type, as defined by the memory model selected during compilation.

For example, in medium-model programs, data pointer arguments are near by default, and code pointer arguments are far by default.

The size of the type of the argument.

Note that if you supply a based pointer as an argument to a function and do not specifically cast it to a far pointer type, a 16-bit offset from the base segment is passed.

Summary: Function prototypes prevent problems that may occur in mixed memory models.

If you provide a function prototype with complete argument types, the compiler performs type-checking and enforces the conversion of actual arguments to the declared type of the corresponding formal argument. However, if no declaration is present or the argument-type list is empty, the compiler will convert nonbased pointer arguments automatically to the default type or the type of the argument, whichever is larger. To avoid mismatched arguments, always use a prototype with the argument types.

For example, the following program produces unexpected results in compact-model, large-model, or huge-model programs.

void main()

{

int __near *x;

char __far *y;

int z = 1;

test_fun( x, y, z ); /* x is coerced to far

pointer in compact,

large, or huge model */

}

int test_fun( int __near *ptr1, char __far *ptr2, int a)

{

printf(“Value of a = %d\n”, a);

}

If the preceding example is compiled as a tiny, small, or medium program, the size of x is 16 bits, the size of y is 32 bits, and the value printed for a is 1.

However, if the example is compiled in compact, large, or huge model, both x and y are automatically converted to far pointers when they are passed to test_fun. Since ptr1, the first parameter of test_fun, is defined as a near pointer argument, it takes only 16 bits of the 32 bits passed to it. The next parameter, ptr2, takes the remaining 16 bits passed to ptr1, plus 16 bits of the 32 bits passed to it. Finally, the third parameter, a, takes the leftover 16 bits from ptr2, instead of the value of z in the main function.

This shifting process does not generate an error message, because both the function call and the function definition are legal. In this case the program does not work as intended, however, since the value assigned to a is not the value intended.

To pass ptr1 as a near pointer, you should include a function prototype that specifically declares this argument for test_fun as a near pointer, as shown below:

/* First, prototype test_fun so the compiler

* knows in advance about the near pointer argument:

*/

int test_fun(int __near*, char __far *, int);

main()

{

int __near *x;

char __far *y;

int z = 1;

test_fun( x, y, z ); /* now, x is not coerced

* to a far pointer; it is

* passed as a near pointer,

* no matter which memory

* model is used

*/

}

int test_fun( int __near *ptr1, char __far *ptr2, int a)

{

printf( “Value of a = %d\n”, a );

}