5 years, 11 months ago.

pointers and arrays

Hi. I suspect this sort of thing gets asked a lot, but I've read through everything I could find about it, and still couldn't work it out, so I figured my best bet was to ask. I'm trying to create a menu system to select which of a selection of boolean arrays gets plotted to an LCD screen. I've got a working general menu function, which accepts menus in the form of arrays (EG; const char* mainMenu[]= {"thing", "other thing", "doofer", "thingamijig",0}; (the 0 at the end of the array's a bodge to allow the size of the array to be calculated when the array is passed through to the function, and decays to a pointer)), and outputs an integer value corresponding to the selected term (EG, if you selected doofer, it would return a value of 2). This works fine, with no problems. I figured the best way to select the arrays to be plotted would be to create an integer array of pointers to said arrays, which I attempted, and which failed. Since I've not tried using pointers much before, I decided to go back to basics, and check that I could make them work in any way at all. I tagged the following lines of code to the start of my program; int foo; int bar = &foo; So far as I can understand, this should generate the integer foo, and then set the following integer bar to contain the memory adress of foo. however, when I try to do this, I get the following error: Error: A value of type "int *" cannot be used to initialize an entity of type "int" in "main.cpp"

The only way I've found to avoid this error coming up is to set bar as a boolean value, which surely makes no sense; the adress of "foo" can't be "true" or "false". Anyone any ideas of what is going on?

2 Answers

5 years, 11 months ago.

C(++) has some safeguards built-in to prevent you from randomly changing one type of variable into another type. Even though from a physical PoV the pointer to an integer fits nicely in an integer (actually should be an unsigned integer), it is not allowed.

The workaround is luckily very simple:

int bar = (int)&foo;

This specifically tells the compiler to change it from a pointer to an integer into an integer, and this is allowed.

Thanks; That seems to work. Unfortunatly, I've now got another follow-up problem; The pointers are supposed to point to a 2d boolean array; so far as I can tell, the pointers are passing through to the function OK, but I'm not sure how to work them back into being a 2d array again. I figure that since the pointer points to a single data block, and the 2d array is arranged in the memory one row after the next, I'll need to input the width of the array somewhere, but beyond that, I'm not sure. I tried the following (both with and without the (bool); initState[x][y]=(bool)*(array+x+88*y); initState[x][y]=(bool)*array[x][y]; All I get is the following error; Error: Expression must have pointer-to-object type in "main.cpp", Line: 314, Col: 42

I'm sure it's something pretty simple yet again. Sorry for being a pest.

posted by Peter Nye 09 May 2015

What type is initState and array?

posted by Erik - 09 May 2015

Oops sorry; initState's a boolean array, and array is the const int I'm using to store the pointer passed through from the array of pointers. I'll post a few of the snippets, to try and make it make a little more sense;

declaration for initState;

bool initState[86][50]; stores the initial state of the buffer

This is the section of code where the pointers get set up;

const char* spaceshipMenu[] = {"image","gosper","glider",0}; array storing the menu entries const int imagePos = (int)&image[0][0], gosperPos = (int)&gosper[0][0], gliderPos = (int)&glider[0][0]; const int spaceshipList[] = {imagePos, gosperPos, gliderPos}; array of pointers

each of the arrays which have pointers to them are initialised like so;

const bool image[48][88];

these arrays are accessed through the following function call;

drawArray(spaceshipList[drawMenu(spaceshipMenu)]);

(Breakdown; drawMenu plots the menu spaceshipMenu, and returns an integer value, which is used to select which of the pointer entries in spaceshipList[] is passed through to drawArray, a function which plots said array to the initState buffer)

Here's the drawArray function;

void drawArray(const int array) plots array to buffer { for (int x=1; x<85; x++) { Loops through pixels for (int y=1; y<49; y++) { initState[x][y]=(bool)*array[x][y]; } } init(); }

posted by Peter Nye 09 May 2015

Probably simplest option:

#include "mbed.h"


void runfun(bool state[86][50]) {
    printf("Value = %d\r\n", state[10][20]);
}

int main()
{
    bool initState[86][50]; 
    runfun(initState);
}

You cannot directly address a pointer as 2d array: Since you need to know both the row and column size to know which value it needs to address.

This also compiles, but you need to figure out yourself where the x and where the y is in the array (so if it is first row x in memory or first column y).

#include "mbed.h"


void runfun(bool *state) {
    printf("Value = %d\r\n", *(state+20+10*50));
}

int main()
{
    bool initState[86][50]; 
    runfun(&initState[0][0]);
}

On a related note, bools are pretty inefficient for storage :). You could also for example use:

uint64_t initState[86]

Of course than you do need to decode the rows properly from the uint64.

Btw code tags are nice ;)

posted by Erik - 10 May 2015

Thanks for the reply; I'll give it a bash if I've got time before the deadline (it's for a uni project). I'll reply again if it works. Sorry about the code tags; Didn't realise you could do that; it does help things make sense. I'll give them a quick try here, see if I can get them to work;

test

#include "mbed.h"
void drawArray(const int array) plots array to buffer { for (int x=1; x<85; x++) { Loops through pixels for (int y=1; y<49; y++) { initState[x][y]=(bool)*array[x][y]; } } init(); }
posted by Peter Nye 10 May 2015
5 years, 11 months ago.

While Eriks answer is correct you wouldn't normally want to store the pointer as an integer, you want to store it as a pointer type.

int foo;
int *bar = &foo;

type int* is a pointer to an integer and so can be set to &foo (the address of foo) without any problems.

c gets a little confusing. A * in a variable declaration means a pointer to. e.g.

int *bar;
// and
int* bar;

are identical, where the space is doesn't matter. They both create a variable of type pointer to an integer called bar, however the first is more commonly used.

However a * outside of a variable declaration means the variable pointed to by the pointer e.g.:

int foo;
int *bar = &foo;

*bar = 5; // the thing pointed to by bar = 5 so now foo = 5.
foo++;
int x = *bar; // x = the value of the thing pointed to by bar = the value of foo = 6.

The reason making bar a bool works is that in c 0 = false, anything else is true. So any numerical value can always be treated as a bool. A value of null (0) is often used to indicate an invalid pointer.

It is very common to see code along the lines of

int foo;
int *bar = null; // initalise bar to 0 to that we know it's not valid.
if (some_condition)
  bar = &foo;
...
...
if (bar) // if bar is valid
  (*bar)++;  // increase the thing bar points to.