Setting void pointer to null.

I have a void pointer that needs to point to NULL, so that the program can determine if it needs to cast it to a type or not, the type is stored as an enumerated type in a class with 0 being an int, and 1 and 2 being the decimal places of a double. So I can't use a value of 0 as an indicator (not sure why it allows me to set the value to 0 anyway, I thought they could only point to other variables and not even be assigned a zero value, as this obviously doesn't correspond to the address of the void pointer). Here is the "proof":

enum TYPE
{
  INT, //zero decimals
  TEMP, //one decimal
  PH //two decimals
};

class menu
{
public:
  int type;
  void *value;
}
menu MAIN;
  MAIN.value=0;
  if ((MAIN.value)==0)
  {
    Serial.println("yes");
  }
  else
    Serial.println("no");
    Serial.println((int)MAIN.value);

OUTPUT:

yes
0

So I need to set the address to 0 on initialisation and then check if it is 0 later on, but &(MAIN.value)=0; doesn't seem to work as it gives the Ivalue required as left operand of assignment error, but Serial.println((int)&MAIN.value); seems to consistently give me an address of 715, so why can I not set to to 0?

That code doesn't do s**t.

MAIN.value=0; is not in a function, neither is the if below that. You code will not compile regardless of the missing main/loop/setup.

As for you question.

but Serial.println((int)&MAIN.value); seems to consistently give me an address of 715, so why can I not set to to 0?

The address of your void pointer is a void**, which is the address to the memory location for your void*. Same goes for '&(MAIN.value)=0;'

As its a pointer to begin with simply assign it ( in a suitable location ).

MAIN.value=0;

I understand now that I was accessing the address of the void pointer itself and not what it is pointing to, thanks for that. I'm not sure I understand why you are telling me first that MAIN.value=0; doesn't do shit and won't compile, and then offer it as a simple solution, especially when I gave you output from my code so obviously it compiles and behaves as expected (but yes I left out the setup but this is where the majority of my example resides).

I guess I'm just getting a bit confused around the variable its pointing to which needs to be cast resembling NULL. How can I differentiate between the address its pointing to being NULL, and if for example, the variable its pointing to's value was 0?

syphex:
I understand now that I was accessing the address of the void pointer itself and not what it is pointing to, thanks for that. I'm not sure I understand why you are telling me first that MAIN.value=0; doesn't do shit and won't compile, and then offer it as a simple solution, especially when I gave you output from my code so obviously it compiles and behaves as expected.

I guess I'm just getting a bit confused around the variable its pointing to which needs to be cast resembling NULL. How can I differentiate between the address its pointing to being NULL, and if for example, the variable its pointing to's value was 0?

I'm happy to help, however the code you provided is not working code, it will not compile... no matter how much you say it does. You either made up the results or did not post your real code.

To compare pointers you simply use a comparison on the pointers

x == y;

Normally to compare pointed to data, you would dereference first.

*x == *y;

However to compare the data, you must use a complete type. Void is a data type (regardless of what people say), however it is incomplete and only void pointers can be subject things like comparisons.

Use a pointer type of whichever type you need, int, char, float...

Pointers don't "point to null". You set the value of the pointer variable to null, so that it points to nothing.

You're right its not the complete code I just posted what I thought was relevant. I just opted to store an int to record the data type instead of having three separate variables in each object, and I'd still need a variable to keep track of which I'm actually using. I can dereference the variables pointed to by the void pointer just fine in this way.

Thanks but thats not what I was trying to imply michinyon, I am talking about setting a void pointer to 0 so that it is not cast into any data type.

I am talking about setting a void pointer to 0 so that it is not cast into any data type.

You have to explicitly cast it, setting it to zero will not prevent a cast to any other pointer type. Not too sure what you are trying to achieve here.

I just opted to store an int to record the data type instead of having three separate variables in each object, and I'd still need a variable to keep track of which I'm actually using.

Perfect candidate for templates.

Post your sketch and class so we can see what you are really intending.

#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

// The shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
uint8_t i=0;

bool UP=0;
bool DOWN=0;
bool LEFT=0;
bool RIGHT=0;
bool SELECT=0;
int waitforinput=1;
// These #defines make it easy to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7
//Define X and Y index
#define Y 0
#define X 1

enum TYPE
{
  INT,
  TEMP,
  PH
};

//TYPE type=MENU;

class menu
{
public:
  int type;
  char name[10];
  byte color;
  byte xpos;// position on the screen
  byte ypos;
  //byte index[2]; //position in the current menu index
  menu*** menulist; //indexed array pointer to group members
  menu* previous_menu; //pointer to previous menu
  void *value;


  menu(char *myname="", byte y=0, byte x=0, byte m_color=0, int c_type=0)
  {
    strcpy(name, myname);
    color=m_color;
    type=c_type;
    menulist=0;
    previous_menu=0;
    value=0;

    if (y>0)
    {
      menulist = new menu**[y+1];
      menulist[y]=0;
      for (byte i=0; i<y; i++)
      { 
        menulist[i] = new menu*[x+1];
        for (byte p=0; p<=x; p++)
          menulist[i][p]=0;
      }
    }
  }

  ~menu(){
    for(int i = 0; menulist[i]!=0; ++i) {
      delete [] menulist[i];
    }
    delete [] menulist;

  }


};

byte backChar[8] = {
  0b11111,
  0b11100,
  0b11110,
  0b10111,
  0b10011,
  0b00011,
  0b00011,
  0b00000
};

menu MAIN("MAIN",3,2,TEAL);
menu menu1("EC:",0,0,RED,PH), menu2("m2",2,3,RED), menu3("menu 3",1,0), menu4("menu 4",1,0), menu5("menu 5",1,1),menu6("menu 6",1,1);

double v1=21.59;
char buffer[5];




menu* current_menu=&MAIN;
byte current_index[2]={
  0,0};
byte index_offset=1;
menu* current_index_menu=current_menu->menulist[current_index[Y]][current_index[X]];


void setup(){
  
  menu1.value=&v1;
  Serial.begin(9600);
  Serial.println("starting");
  lcd.begin(16,2);
  lcd.setBacklight(WHITE);
  lcd.createChar(0, backChar);
  lcd.setCursor(-2,0);
  lcd.print("hello");
  delay(1000);
  lcd.clear();
  menu2.previous_menu=&MAIN;
  menu2.menulist[0][0]=&MAIN;
  menu5.previous_menu=&menu2;
  menu5.menulist[0][0]=&menu2;
  menu6.previous_menu=&menu2;
  menu6.menulist[0][0]=&menu2;
  menu2.menulist[0][1]=&menu5;
  menu2.menulist[0][2]=&menu6;
  menu2.menulist[1][1]=&menu3;
  menu2.menulist[1][2]=&menu4;
  menu2.menulist[1][0]=&menu3;
  MAIN.menulist[0][0]=&menu1;
  MAIN.menulist[0][1]=&menu2;
  MAIN.menulist[1][0]=&menu3;
  MAIN.menulist[2][0]=&menu4;
  MAIN.previous_menu=&MAIN;
  current_index_menu=current_menu->menulist[current_index[Y]][current_index[X]];
  MAIN.value=0;
  if (menu3.menulist==0)
  {
    Serial.println("yes");
  }
  else
    Serial.println("no");
    Serial.println((int)&MAIN.value);
  Serial.println(*(double*) current_menu->menulist[current_index[Y]][current_index[X]]->value);
  Serial.println(*(double*) current_index_menu->value);
  Serial.println(strlen(dtostrf(*(double*) current_index_menu->value,3,current_index_menu->type,buffer)));
  //Serial.println(strlendtostrf(*(double*) current_index_menu->value,3,2,buffer));
  //Serial.println(strlen(current_menu->menulist[0][0]->name));
  display_menu();
}

void loop(){
  //current_index_menu=current_menu->menulist[current_index[Y]][current_index[X]];
  //Serial.println(waitforinput);
  uint8_t buttons = lcd.readButtons();
  if (waitforinput>1) waitforinput-=1;
  else{
    if (buttons) {
      current_index_menu=current_menu->menulist[current_index[Y]][current_index[X]];
      waitforinput=2;
      lcd.clear();
      
      if (buttons & BUTTON_UP) {
        UP=true;
        if (current_index[Y]==0)
        {
          for (i=0; current_menu->menulist[current_index[Y]+1][current_index[X]]!=0; i++)
          {
            current_index[Y]=i; //replace with find 0 index
            index_offset=i;
          }
        }
        else {
          if (index_offset-current_index[Y]==1) index_offset--; 
          current_index[Y]--;
        }
      }
      if (buttons & BUTTON_DOWN) {
        DOWN=true;
        if (current_menu->menulist[current_index[Y]+1]==0)
        { 
          index_offset=1;
          current_index[Y]=0;
        }
        else {
          if (current_index[Y]==index_offset) index_offset++; 
          current_index[Y]++;
        }
      }
      if (buttons & BUTTON_LEFT) {
        LEFT=true;
        if (current_index[X]==0)
        {
          for (i=0; current_menu->menulist[current_index[Y]][current_index[X]+1]!=0; i++)
            current_index[X]=i; 
        }
        else current_index[X]--;
      }
      if (buttons & BUTTON_RIGHT) {
        RIGHT=true;
        if (current_menu->menulist[current_index[Y]][current_index[X]+1]==0)
          current_index[X]=0;
        else
          current_index[X]+=1;
      }
      if (buttons & BUTTON_SELECT) {
        SELECT=true;
        waitforinput=3;
        if (current_index_menu->previous_menu==0)
          current_index_menu->previous_menu=current_menu;
        if (current_index_menu->color==0)
          current_index_menu->color=current_menu->color;
        lcd.setBacklight(current_index_menu->color);
        current_menu=current_index_menu;
        current_index[X]=0;
        current_index[Y]=0;
        //Serial.println(current_menu->previous_menu->name);
      }
      Serial.println(index_offset);
      display_menu();
    }

  }


  //display_menu();
  lcd.setCursor(15,0);
  lcd.print(current_index[Y]);
  lcd.setCursor(15,1);
  lcd.print(current_index[X]);
}

void display_menu()
{

  for (int i=index_offset-1; i<=index_offset; i++)
  {

    //display_selection();
    byte xpos=2;
    for(int p=0; (current_menu->menulist[i][p])!=0; p++)
    {

      current_index_menu=current_menu->menulist[i][p];
      //Serial.println(p);
      //Serial.print(" ");
      // delay(1000);
      //lcd.setCursor(xpos);
      lcd.setCursor(xpos,1-(index_offset-i));
      if (current_index_menu!=current_menu)
      if (current_index_menu==current_menu->previous_menu)
        {
          lcd.setCursor(0,0);
          lcd.write((uint8_t)0);
          if (current_index[Y]==i && current_index[X]==p)
          {
          lcd.setCursor(0,1);
          lcd.print("^");
          }
          xpos+=2;         
        }
        else      
      {
        if ((current_index_menu->menulist!=0) && (current_index[Y]==i && current_index[X]==p))
        {
        lcd.setCursor(xpos-1,1-(index_offset-i));
        lcd.print(">");
        lcd.print(current_index_menu->name);
        lcd.print("<");
        }
        else
        lcd.print(current_index_menu->name);
        
        xpos+=strlen(current_index_menu->name);
        
        
        
        if (current_index_menu->value!=0)
        {
          if (current_index[Y]==i && current_index[X]==p)
          {
            lcd.setCursor(xpos-1,1-(index_offset-i));
            lcd.print(">");
          }
          lcd.setCursor(xpos,1-(index_offset-i));
          
          lcd.print (*(double*)(current_index_menu->value),current_index_menu->type); 
          //lcd.print("<");
          xpos+=strlen(dtostrf(*(double*) current_index_menu->value,3,current_index_menu->type,buffer));
          
          if (current_index[Y]==i && current_index[X]==p)
          {
            lcd.setCursor(xpos,1-(index_offset-i));
            lcd.print("<");
          }
        }
        xpos++;
      }
      //Serial.println();
    }
  }

}

however it is incomplete and only void pointers can be subject things like comparisons.

Say what? Is there a non- missing from that statement somewhere?

Am I missing something here?

Can't one just do this:

char *buffer = NULL;

?

If you will be setting your void pointers to NULL, you need to check for NULL pointers before you dereference them. You also need to manage storage for your pointers. A better approach might be to use a union.

http://www.cplusplus.com/doc/tutorial/other_data_types/

PaulS:

however it is incomplete and only void pointers can be subject things like comparisons.

Say what? Is there a non- missing from that statement somewhere?

Nope, a void pointer can be compared as it is a simple pointer and pointers are always the same size. You cannot dereference a void pointer and compare the result with another dereferenced pointer type. There is no layout information for the compiler to generate any comparison.

I don't know what the confusion about what I'm trying to achieve is for, I posted the relevant information in the first post. An enum holds the type, only when the pointer isn't NULL. Otherwise it is "ignored" by the code, I did not mean that setting it to NULL will implicitly cause it to avoid being cast, just using a simple switch statement to check for the type (an int) and acting accordingly.

Example from learnpp.com:

enum Type
{
    INT,
    FLOAT,
    STRING,
};
 
void Print(void *pValue, Type eType)
{
    using namespace std;
    switch (eType)
    {
        case INT:
            cout << *static_cast<int*>(pValue) << endl;
            break;
        case FLOAT:
            cout << *static_cast<float*>(pValue) << endl;
            break;
        case STRING:
            cout << static_cast<char*>(pValue) << endl;
            break;
    }
}
 
int main()
{
    int nValue = 5;
    float fValue = 7.5;
    char *szValue = "Mollie";
 
    Print(&nValue, INT);
    Print(&fValue, FLOAT);
    Print(szValue, STRING);
    return 0;
}

For the menu class, it has no inheritance. It has variables to be a menu to branch into other menu's, or value to be changed by the user via the buttons, or both. So when a menu's void pointer (which points to a value to display/change) is NULL, then it is a menu only, otherwise it checks the type; 0, 1, and 2 (int, double ##.#, and double #.## respectively).

To be honest I didn't know there was a NULL keyword, so what exactly is the difference between setting a void pointer to 0, and setting it to NULL?