Jump to content

  • Log In with Google      Sign In   
  • Create Account


Passing a float as a pointer.


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
11 replies to this topic

#1 harshman_chris   Members   -  Reputation: 184

Like
0Likes
Like

Posted 30 January 2013 - 03:35 PM

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?

 


Sponsor:

#2 Cornstalks   Crossbones+   -  Reputation: 6966

Like
5Likes
Like

Posted 30 January 2013 - 03:46 PM

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.


[ 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 ]

#3 Ectara   Crossbones+   -  Reputation: 2764

Like
0Likes
Like

Posted 30 January 2013 - 04:04 PM

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.



#4 harshman_chris   Members   -  Reputation: 184

Like
0Likes
Like

Posted 30 January 2013 - 04:20 PM

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.



#5 Cornstalks   Crossbones+   -  Reputation: 6966

Like
0Likes
Like

Posted 30 January 2013 - 04:27 PM

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).


[ 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 ]

#6 Ectara   Crossbones+   -  Reputation: 2764

Like
0Likes
Like

Posted 30 January 2013 - 04:31 PM

(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.
 

#7 harshman_chris   Members   -  Reputation: 184

Like
0Likes
Like

Posted 30 January 2013 - 05:47 PM

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.



#8 L. Spiro   Crossbones+   -  Reputation: 12216

Like
0Likes
Like

Posted 30 January 2013 - 06:18 PM

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


It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#9 Ectara   Crossbones+   -  Reputation: 2764

Like
0Likes
Like

Posted 30 January 2013 - 06:50 PM

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.


Edited by Ectara, 30 January 2013 - 06:51 PM.


#10 BornToCode   Members   -  Reputation: 900

Like
0Likes
Like

Posted 31 January 2013 - 01:04 AM

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.
 


Edited by BornToCode, 31 January 2013 - 01:06 AM.


#11 Cornstalks   Crossbones+   -  Reputation: 6966

Like
1Likes
Like

Posted 31 January 2013 - 01:30 AM

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.
}

That's undefined behavior right there. I don't think you can rely on undefined behavior to come to any kind of meaningful conclusions about what the standard guarantees.

 

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.

Without trying to get super technical in this thread, temporaries may or may not have addresses associated with them, as they can potentially be completely optimized away or live entirely in a register instead of in memory. But yes, as you have noticed, you can pass a temporary or literal by const reference, which implies it's got some address or memory location associated with it (this is most easily proven by simply taking and printing the address of the const reference). A situation like this would fall under the "the temporary is just a guest in a temporary home" situation I described at the end. It's also important to note that when you print out that address, it is not still valid (that is, the temporary no longer exists in any way, shape, or form (as far as the standard guarantees), so that address you're printing out is just the temporary's old address, not a currently valid address (because the temporary doesn't even exist... how can you address it?))


Edited by Cornstalks, 31 January 2013 - 01:34 AM.

[ 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 ]

#12 harshman_chris   Members   -  Reputation: 184

Like
1Likes
Like

Posted 31 January 2013 - 05:08 PM

So I am going back to the drawing board, to redevelop how I want to plan out my engine structure.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS