Keil Logo

Pointer Conversions

The Cx51 Compiler converts between memory-specific pointers and generic pointers. Pointer conversions may be forced by explicit program code using type casts or may be coerced by the compiler implicitly.

The Cx51 Compiler converts a memory-specific pointer into a generic pointer when the memory-specific pointer is passed as an argument to a function which requires a generic pointer. This is the case for functions such as printf, sprintf, and gets which use generic 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 pointer to code space, is automatically converted or coerced into a 3-byte generic pointer. This is done because the prototype for printf requires a generic pointer as the first argument.

Note

  • A memory-specific pointer used as an argument to a function is always converted into a generic pointer if no function prototype is present. This may cause errors if the called function actually expects a shorter pointer type as an argument. You may avoid these kinds of errors in programs by using include files and prototyping all external functions. This guarantees conversion of the necessary types by the compiler and ensures that the compiler detects and reports type conversion errors.

The following table details the process to convert generic pointers (*) to memory-specific pointers (code *, xdata *, data *, idata *, pdata *).

Convert
From
Convert
To
Description
* code * The offset (2 bytes) of the generic pointer is used.
* xdata * The offset (2 bytes) of the generic pointer is used.
* data * The low-order byte of the generic pointer offset is used. The high-order byte is discarded.
* idata * The low-order byte of the generic pointer offset is used. The high-order byte is discarded.
* pdata * The low-order byte of the generic pointer offset is used. The high-order byte is discarded.

The following table describes the process to convert memory-specific pointers (code *, xdata *, data *, idata *, and pdata *) to generic pointers (*).

Convert
From
Convert
To
Description
code * * The memory type of the generic pointer is set to 0xFF for code. The 2-byte offset of the code * is used as the offset.
xdata * * The memory type of the generic pointer is set to 0x01 for xdata. The 2-byte offset of the xdata * is used as the offset.
data * * The 1-byte offset of the idata */data * is converted to an unsigned int and used as the offset.
idata * * The memory type of the generic pointer is set to 0x00 for idata/data.
pdata * * The memory type of the generic pointer is set to 0xFE for pdata. The 1-byte offset of the pdata * is converted to an unsigned int and used as the offset.

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

stmt level  source
   1        int *p1;           /* generic 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 generic* */
   8   1    p1 = p3;           /* idata* to generic* */
   9   1    p1 = p4;           /* code*  to generic* */
  10   1
  11   1    p4 = p1;           /* generic* to code* */
  12   1    p3 = p1;           /* generic* to idata* */
  13   1    p2 = p1;           /* generic* 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 # 7
0000 750001 R   MOV  p1,#01H
0003 850000 R   MOV  p1+01H,p2
0006 850000 R   MOV  p1+02H,p2+01H
                      ; SOURCE LINE # 8
0009 750000 R   MOV  p1,#00H
000C 750000 R   MOV  p1+01H,#00H
000F 850000 R   MOV  p1+02H,p3
                      ; SOURCE LINE # 9
0012 7B05       MOV  R3,#0FFH
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)
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.