Passing a float as a pointer.

Started by
10 comments, last by harshman_chris 11 years, 2 months ago

So I am trying to pass the below value to a float*, it returns a float


enviroment->getDirectionalLight()->getAmbientIntensity()

Here is what I am trying to pass it into.


void addUniform(std::string _id, float* _value);

getShader()->addUniform("directionalLight.base.ambientIntensity",&enviroment->getDirectionalLight()->getAmbientIntensity());

Unfortunately, it gives me this error


error C2102: '&' requires l-value

I dont understand this error, or a way around it?

Advertisement

There are different value types in C++ types. To take the address of something with &, it needs to be an l-value. Temporary variables, like what enviroment->getDirectionalLight()->getAmbientIntensity() returns, are r-values, which means you can't take their address.

Think of it like this: Where does the float returned by enviroment->getDirectionalLight()->getAmbientIntensity() live? Where is its home? Answer: it doesn't have one. It's "homeless." It's just a temporary float that's being returned by a function, and so it never gets a "home" assigned to it. If something doesn't have a home, how can you take its address? You can't. The address points to "home," and thus if you could take its address it would have a home in the first place!

Why is this important? Well, look at that function. It's taking a pointer to a float. That means the function has the power and ability to change that float. But that float is temporarily existing. You can't change a temporary like that. If you could do that, then why not be able to do int* x = &2; *x = 3; (uh oh... did we just change 2 to now be 3? that's (one reason) why something like this isn't legal).

Note that this is a pretty high level explanation. You could get super technical and say that the temporary float does (or even better: might) have a home, but I don't really want to get into those details too much. If you want to view it like this, just think of it as a super temporary home that has some special rules you can't mess with. Kind of like a guest-home. The float is just a guest at the home, it doesn't "own" the home. You can't go in and start changing things in a home you don't own. Not legally, at least.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

Another question is why does the function take a pointer? If it were returning a value, it could easily just return a float value, unless it is expected to read and write this value over time; in the latter case, passing the return value of that function is immediately a bad idea. This strikes me as a function that takes an array of float values, so even if you assigned the temporary to a variable, then sent its address, that'd be trouble.

My basic idea is that I need to store the memory address to several float's and int's, so that I can access the values at a later point from a different class without having to hardcode the calls.

My basic idea is that I need to store the memory address to several float's and int's, so that I can access the values at a later point from a different class without having to hardcode the calls.

So don't use pointers, but use values (I see no reason there why you need the memory address):

struct MyStruct
{
    int x;
 
    void assign(int value)
    {
        x = value; // Saving it for later!
    }
 
    void useValue()
    {
        std::cout << "x is " << x << std::endl; // Now use it later!
    }
};
 
MyStruct s;
s.assign(someFunctionThatComputesStuff());
// ... some time later ...
s.useValue(); // does *NOT* re-call someFunctionThatComputesStuff()

You can also make a std::vector of floats or ints if you need (but keeping track of what value represents what might get confusing if each value is supposed to be used differently).

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

(I see no reason there why you need the memory address)


He likely is trying to say that the value that is returned is expected change while he's holding the pointer to it, and he wants to always have the updated value without having to get it again each time.

Then this will be a problem; technically, the temporary value might be in memory, or it might not be in memory at all. Even if it is, it's address will likely be different each time it is called. You'll have to find a way around it.

I would suggest getting a pointer to the data that the function returns (might not be a good idea, because it has an interface in place to get it, so handling it yourself might defy assumptions that the code makes), or holding on to the data in some sort of cache like Cornstalks mentioned, and having some sort of system to know when it is time to update it.

The problem with watching for an update is that now a large section of my code needs to be hard coded to refresh values.

Where as if I can store pointers to the piece of data I will will not have to hard code that side of things.

The problem with watching for an update is that now a large section of my code needs to be hard coded to refresh values.

Where as if I can store pointers to the piece of data I will will not have to hard code that side of things.

No, you just have an even-worse slew of new problems to handle, such as life-times of the pointers.
Even if you went with your pointer system you would still have to “hard-code” the telling to the shader that the pointer is no longer valid.

I don’t believe you are using the word “hard-code” correctly either.
What does that mean and how does it relate to a system such as this?
When some things change, sometimes other systems or objects need to be notified and updated. This isn’t hard-coding. It’s just…coding.

Besides that, you are trying to escape a simple update-when-changed system for a pointer-based system which means your intention is to set the pointer once and leave it.
That means you have no intention of using the same shader between multiple objects as that would require re-updating the pointer for each object (which would make the pointer system pointless since that many re-updates would mean that the shader would always have the most up-to-date value in it anyway).
The point is you can’t share your shaders and this is a major loss in both resources and performance.

Basically, your overall design needs to be re-evaluated, and your real underlying issue isn’t as simple as floats and pointers. To solve this issue you must look beyond the beyond, young Kimosabe. You must acknowledge that “grey” does not have an “a” in it, and you can’t ignore the chocolate cake any longer. The time has come…

A good start would be to explain what you mean by “hard-coded” and what exactly is so wrong with your current system that you feel the need to make an even-worse system.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

You must acknowledge that “grey” does not have an “a” in it


In my country's variant of English, its preferred spelling is "gray", with "grey" as an accepted alternative. smile.png

Also, I agree with figuring out exactly what you need and establishing why you need it, rather than making several drawn out patches to a system that likely wasn't what you had in mind when you started.

There are different value types in C++ types. To take the address of something with &, it needs to be an l-value. Temporary variables, like what enviroment->getDirectionalLight()->getAmbientIntensity() returns, are r-values, which means you can't take their address.



Think of it like this: Where does the float returned by enviroment->getDirectionalLight()->getAmbientIntensity() live? Where is its home? Answer: it doesn't have one. It's "homeless." It's just a temporary float that's being returned by a function, and so it never gets a "home" assigned to it. If something doesn't have a home, how can you take its address? You can't. The address points to "home," and thus if you could take its address it would have a home in the first place!



Why is this important? Well, look at that function. It's taking a pointer to a float. That means the function has the power and ability to change that float. But that float is temporarily existing. You can't change a temporary like that. If you could do that, then why not be able to do int* x = &2; *x = 3; (uh oh... did we just change 2 to now be 3? that's (one reason) why something like this isn't legal).







Note that this is a pretty high level explanation. You could get super technical and say that the temporary float does (or even better: might) have a home, but I don't really want to get into those details too much. If you want to view it like this, just think of it as a super temporary home that has some special rules you can't mess with. Kind of like a guest-home. The float is just a guest at the home, it doesn't "own" the home. You can't go in and start changing things in a home you don't own. Not legally, at least.

Well that is kind of true. All temporary file does have a home, because i just tried that

int* foo(const int& x)
{
int* t = (int*)&x;
*t=22;
return t;
}
void main()
{
int* ref = foo(12);

cout<<ref<<endl; //This is stil pointing to the temporary variable address.
}

And i was a able to modify 12 to 22. Also when i try printing the address of 12 it does print out an Address. The interesting thing is that the return value when i print it the address is still valid. The thing that was very interesting though is that if you look at the Assembly you will notice that the value that is assign to foo is still valid in the assembly code.

This topic is closed to new replies.

Advertisement