Relative Variable Addresses

Started by
7 comments, last by GameDev.net 19 years, 6 months ago
Hey, I'm writing a menu system thats basically hard-coded into my application, and I require that menu items directly affect variables. This is pretty easy as I can just get the address of a variable and the menu code can set or change the variable as it is clicked. However, I also need context sensitive menus or object-related menus. So different objects on the screen when clicked-on, have a menu which can DIRECTLY alter its variables. So... I was wondering whats the best method of finding the relative variable address of a type of class! Once, I know the offset, I'm just adding it to the class address that's selected and applying whatever... I can find the offset at runtime obviously by subtracting the address of a variable within an instance of the class by the address of that instance, which i encapsulted into a macro: #define FindRelativeAddress(result,object, variable) {object fra; result = (long)&fra.variable-(long)&fra} Not a nice looking macro :-p, nor is it by far the best way of doing this, but unfortunately, it doesn't really work for how I want to get the address of a variable... This code needs to be executed and I want the value to just EXIST within an array of numbers.... If anyone knows how? (im thinking somthing like "sizeof()" then lemme know! :-p Regards, Chris
Advertisement
This is a little hacky, but it works. You can cast NULL to be a pointer of your class type, then dereference it to find the offset. Then convert that address to an int, and that will give you the desired offset.


class test
{
int x;
int y;
};


void function()
{
...

test *pTest = (test*)NULL;
int nXOffset = (int)&pTest->x;
int nYOffset = (int)&pTest->y;

...
}
I did something similar for my scripting language:
#define OFFSET(classname,varname) ((&((classname*)NULL)->varname)
At least, I think thats what it was. You don't need to have an instance of the class to get the address of the member variable, you can use NULL to get the address relative to 0 (which is what you need).
But no, theres no equivalent of sizeof() or any other compiler macro/function that I know of.
Pointers to members?

class aClass {  int field1, field2, field3, field4;};void func() {  int aClass::* aPointerToField3;  aPointerToField3 = &aClass::field3;  // ...  aClass obj;  obj.*aPointerToField3 = 3; // this sets obj.field3 to 3}


Definitely one of the more obscure C++ features, but I think you've found one of the rare situations that could use them.
If I'm not mistaken, the class offset is compiler dependant. Rather, the compiler can order the members of a class however it likes to make things faster.

Why don't you pass a reference [or something else to specify the context] to the context sensitive menu? That's the way I've been doing it. But perhaps I've misunderstood your needs.
Pointers to members!, lol... okie. Why didn't i think of that, I came accross the whole type-casting of pointers to members, but never made the connection that it WAS actualy a type of pointer, hehe... c++ is fun! :-p

Thank you!
Chris
Basically, I wanted to write a set of macros so that I could write somthing like the following:

-----

// Class
struct object {
bool active;
long life;
};

// Resource Script (uses macros that replace to bytes)
byte resource[] = {
menu ("Object Properties", object)
item ("Active", object::active, BOOL|TOGGLE)
item ("Life", object::life, LONG|SET)
item ("X", object::x, LONG|SET)
end
};

-----

Then, inside the editor, you select an object and it brings up a menu, with the two items, "Active" and "Life", next to each item are controls to alter the state of the variable!.

Using the flags specified in the resource, the editor decides which type of control to draw and use, and also the type of variable thats being altered!

Ah, I would probably just make that a function like:
menu *object_menu(object *objptr){// Takes an object, returns a created menu for itmenu *rtn;rtn=new menu;toggle *foo=create toggle("Active",&objptr->active);attach foo -> rtn;numinput *bar=create numinput("Life",&objptr->life);attach bar -> rtn;return (rtn);}


I actually do something sort of like this in my current project for context sensitive menus. Unfortunately it's rather messy since this was my first try at any sort of gui system.
Quote:Original post by pinacolada
Pointers to members?


class aClass {
int field1, field2, field3, field4;
};

void func() {

int aClass::* aPointerToField3;
aPointerToField3 = &aClass::field3;
// ...
aClass obj;
obj.*aPointerToField3 = 3; // this sets obj.field3 to 3
}


Definitely one of the more obscure C++ features, but I think you've found one of the rare situations that could use them.


Actually, using pointer to members will require a strong typing between the elements to be modified and the classes that can be used for them. The technique the original AP and Evil Steve posted will work for generic objects. If you have a slider bar, and you want to modify a float, you don't need to create multiple definitions for all possible types of classes to bind to your sliderbar, or whatever. You can hook your slider up to float Particle::opacity, or float Character::animation_speed or whatever, since you can find the offset for the float using the macro approach. If you were to use pointers to members, you would need 2 functions for your slider bar, one to bind to float *Particle::opacity and another for float *Character::animation_speed.

Quote:Original post by Telastyn
If I'm not mistaken, the class offset is compiler dependant. Rather, the compiler can order the members of a class however it likes to make things faster.


Telastyn, you are technically correct, but it won't matter in this case, because the offsets are being calculated by the same compiler. The offsets will all be correct.

This topic is closed to new replies.

Advertisement