Pointer for ROM variable in a RAM variable?

c, mplab-c18

Solution

What is the definition of the `rom` macro? I'm guessing that it expands to `const` (and possibly a compiler-specific `__attribute__` or somesuch), because the compiler is complaining about a "type qualifier mismatch", which refers to a `const` or `volatile` mismatch.

What that means is that you're trying to implicitly cast a pointer to constant data into a pointer to non-constant data. This code should generate the same warning with your compiler:

const int x = 0;
int *y = &x;  // &x is "pointer to const" but y is "pointer to non-const"

To fix it, you need to declare that your `position` pointer is a pointer to constant data (which, depending on the definition of the `rom` macro, should be done with either `rom` or the `const` qualifier):

// Declare a non-constant pointer to constant data
const struct block *position = &map[0];

At each pointer level, you can have a `const` qualifier or lack thereof, and likewise for the base non-pointer object. So, a single-level pointer can have 4 different variants:

int *x;  // Non-constant pointer to non-constant data
int *const x;  // Constant pointer to non-constant data
const int *x;  // Non-constant pointer to constant data
int const *x;  // Same as above
const int *const x;  // Constant pointer to constant data
int const *const x;  // Same as above

Note that `int const` and `const int` are equivalent, but otherwise the placement of `const` does matter.

Problem

I'm doing a project using the Microchip C18 compiler. I have a struct called a block that points to other blocks (north east south west). These blocks will make me a map. I then have a pointer that I use to evaluate everything. Just using RAM it looks like: ``` struct block{ struct block *north; struct block *east; struct block *south; struct block *west; }; struct block map[5] = { // just a simple line. { NULL, &map[1], NULL, NULL }, { NULL, &map[2], NULL, &map[0]}, { NULL, &map[3], NULL, &map[2]}, { NULL, &map[4], NULL, &map[3]}, { NULL, NULL, NULL, &map[4]} }; struct block* position = &map[0]; ``` This lets me do stuff like: ``` void goWest() { if(position -> west != NULL) position = position -> west; } ``` Problem is that I've run out of RAM in my project and need to use ROM What I have so far is: ``` struct block{ rom struct block *north; rom struct block *east; rom struct block *south; rom struct block *west; }; rom struct block map[5] = { // just a simple line. { NULL, &map[1], NULL, NULL }, { NULL, &map[2], NULL, &map[0]}, { NULL, &map[3], NULL, &map[2]}, { NULL, &map[4], NULL, &map[3]}, { NULL, NULL, NULL, &map[4]} }; ``` I've done some debugging and can tell the above part works, but trying to make the position pointer is giving me grief. so I guess my question is: How do I hold the ROM variable addresses in a pointer which I can edit the values of? When i try: ``` struct block *position = &map[0]; ``` I get "Warning [2066] type qualifier mismatch in assignment" I realize that a ROM variable and RAM variable are two different things, but I have no idea what to do.

Original source