Crossware

Table of Contents        Previous topic       Next topic       

C COMPILER->8051 Specific Features->Generic Pointers

Generic pointers are pointers that can point to any memory area.  They are 3 bytes wide, with the third byte containing information about the memory area that it currently points at.  The third byte can contain the values 1 to 5 which have the following meanings:
    
Value    Memory area

1    idata
2    xdata
3    reserved for future use
4    data (including bdata)
5    code

    
You can use these values to specifically assign a constant to a generic pointer.  For instance if you wanted to assign the external data memory address 8200 (hex) to a generic pointer, the declaration and assignment might be as follows:
    
    char _generic *pGeneric = 0X28200;

A generic pointers can be created in a number of ways:
    

    char _generic *pGeneric = 0X28200;
    char *pAnother;
    pAnother = pGeneric;

    int func(const char *pszText)
    {
        int nCount = 0;
        while (*pszText != '\0')
            nCount++;
        return nCount;
    }

This last method of declaring a function argument as a pointer to const is the most common method by which generic pointers are created and the most important for the programmer to understand. It is fundamental to allowing all of the standard C library functions to work unmodified whatever the selected memory model while avoiding the inefficiencies of generic pointers where they are not required.

The logic is as follows.  When the compiler sees a function argument that is a pointer to const, it can assume that there is a possibility that the object that it points to could be in code space.  However, it cannot rule out the possibility that the object might be in data space.  Therefore it is will create a generic pointer.  This works perfectly with the standard C library where const is used for all function arguments that might be in rom or ram.  For instance strcpy() is declared as:

char *strcpy(char* pszDestination, const char* pszSource);

pszSource may for instance be a string literal which is automatically located in code space:

    char szBuffer[50];
    strcpy(szBuffer, Hello world);

or pszSource may be in ram:

    char szBuffer[50];
    char szText[] = Hello world;
    strcpy(szBuffer, szText);

pszDestination however must always be in data space because the strcpy() function is going to write data into it.

If you are going to write your own functions that have arguments that need to be generic pointers, you can if you wish declare it using the _generic keyword, but it much more portable and has the same effect if you declare it as a pointer to const.

To prevent a function argument that is pointer to const from becoming a generic pointer then you need to specifically qualify it with the appropriate qualifier.  For instance if you want pszMessage to point to code space only, then you might declare a function as:

void func(const char _code *pszMessage);

Note that it is only with function arguments that pointers to const become generic pointers.  If you declare a pointer to const anywhere else, then unless you qualify it, the smart pointer technology will take over and work out the type that it should be.