Pointer Conversions

C51 can convert between typed pointers and untyped pointers. Pointer conversions can be forced by explicit program code using type casts or can be coerced by the compiler.

The C51 compiler coerces a typed pointer into an untyped pointer when the typed pointer is passed as an argument to a function which requires an untyped pointer. This is the case for functions such as printf, sprintf, and gets which use untyped pointers as arguments. For example:
extern int printf (
void *format, ...);

extern int myfunc (
void code *p,
int xdata *pq);

int xdata *px;
char code *fmt = "value = %d | %04XH\n";

void debug_print (void)
{
printf (fmt, *px, *px); /* fmt is converted */
myfunc (fmt, px); /* no conversions */
}

In the call to printf, the argument fmt  which represents a 2-byte code pointer is automatically converted or coerced into a 3-byte untyped pointer. This is done because the prototype for printf requires an untyped pointer as the first argument.

NOTE
A typed pointer used as an argument to a function is always converted into an untyped pointer if no function prototype is present. This can cause errors if the called function actually expects a shorter pointer as an argument. In order to avoid these kinds of errors in programs, use #include files and prototype all external functions. This guarantees conversion of the necessary types by the compiler and increases the likelihood that the compiler will detect type conversion errors.

The following table details the process involved in converting untyped pointers (untyped *) to typed pointers (code *, xdata *, idata *, data *, pdata *).

Conversion Type

Description

untyped * to code *

The offset section (2 bytes) of the untyped pointer is used.

untyped * to xdata *

The offset section (2 bytes) of the untyped pointer is used.

untyped * to idata *

The low-order byte of the typed pointer offset is used. The high-order byte is discarded.

untyped * to data *

The low-order byte of the typed pointer offset is used. The high-order byte is discarded.

untyped * to pdata *

The low-order byte of the typed pointer offset is used. The high-order byte is discarded.

The following table describes the process involved in converting typed pointers (code *, xdata *, idata *, data *, pdata *) to untyped pointers (untyped *).

Conversion Type

Description

xdata * to untyped *

The memory type of the untyped pointer is set to 2 for xdata. The 2-byte offset of the xdata * is used.

code * to untyped *

The memory type of the untyped pointer is set to 5 for code. The 2-byte offset of the code * is used.

idata * to untyped *

The memory type of the untyped pointer is set to 1 for idata. The 1-byte offset of the idata * is converted to an unsigned int and used as the offset.

data * to untyped *

The memory type of the untyped pointer is set to 4 for data. The 1-byte offset of the data * is converted to an unsigned int and used as the offset.

pdata * to untyped *

The memory type of the untyped pointer is set to 3 for pdata. The 1-byte offset of the pdata * is converted to an unsigned int and used as the offset.

The following example listing illustrates a few pointer conversions and the resulting code:

.
.
.
stmt level source
1 int *p1; /* untyped ptr (3 bytes) */
2 int xdata *p2; /* xdata ptr (2 bytes) */
3 int idata *p3; /* idata ptr (1 byte) */
4 int code *p4; /* code ptr (2 bytes */
5
6 void pconvert (void) {
7 1 p1 = p2; /* xdata* to untyped* */
8 1 p1 = p3; /* idata* to untyped* */
9 1 p1 = p4; /* code* to untyped* */
10 1
11 1 p4 = p1; /* untyped* to code* */
12 1 p3 = p1; /* untyped* to idata* */
13 1 p2 = p1; /* untyped* to xdata* */
14 1
15 1 p2 = p3; /* idata* to xdata* (WARN) */
*** WARNING 259 IN LINE 15 OF P.C: pointer: different mspace
16 1 p3 = p4; /* code* to idata* (WARN) */
*** WARNING 259 IN LINE 16 OF P.C: pointer: different mspace
17 1 }
.
.
.
ASSEMBLY LISTING OF GENERATED OBJECT CODE


; FUNCTION pconvert (BEGIN)
; SOURCE LINE # 6
; SOURCE LINE # 7
0000 750002 R MOV p1,#02H
0003 850000 R MOV p1+01H,p2
0006 850000 R MOV p1+02H,p2+01H
; SOURCE LINE # 8
0009 750001 R MOV p1,#01H
000C 750000 R MOV p1+01H,#00H
000F 850000 R MOV p1+02H,p3
; SOURCE LINE # 9
0012 7B05 MOV R3,#05H
0014 AA00 R MOV R2,p4
0016 A900 R MOV R1,p4+01H
0018 8B00 R MOV p1,R3
001A 8A00 R MOV p1+01H,R2
001C 8900 R MOV p1+02H,R1
; SOURCE LINE # 11
001E AE02 MOV R6,AR2
0020 AF01 MOV R7,AR1
0022 8E00 R MOV p4,R6
0024 8F00 R MOV p4+01H,R7
; SOURCE LINE # 12
0026 AF01 MOV R7,AR1
0028 8F00 R MOV p3,R7
; SOURCE LINE # 13
002A AE02 MOV R6,AR2
002C 8E00 R MOV p2,R6
002E 8F00 R MOV p2+01H,R7
; SOURCE LINE # 15
0030 750000 R MOV p2,#00H
0033 8F00 R MOV p2+01H,R7
; SOURCE LINE # 16
0035 850000 R MOV p3,p4+01H
; SOURCE LINE # 17
0038 22 RET
; FUNCTION pconvert (END)
.
.
.