28 Oct, 2010, Runter wrote in the 41st comment:
Votes: 0
Yeah. That's what had been suggested. I don't like this solution at all. Why? Because you have to do all that and you still have two variables. The pointer is 4 or 8 bytes and the int off the stack is another 4 or 8 bytes. If you needed a third flag I suppose you could make a pointer to a pointer to an int. Then you could have two zero values. The best solution here is obviously an abstract datatype representing an account if you're wanting to do anything more fancy than track a single value.
28 Oct, 2010, bbailey wrote in the 42nd comment:
Votes: 0
David Haley said:
Yes, that us entirely possible and correct - it's what I suggested in post #28 (check the chronological order of those citations). I would ask though that people not speak of the "existence" of variables. That means something different, not whether or not they have a non-zero value. A pointer exists when it is declared, not when it is given a value. This is important when you consider that a suggestion was given to use __if_exists which does test for true existence (but only at compile-time).

Basically C doesn't have the same dynamic notion of existence that languages like Python do. It can be implemented of course as something else, but then you're testing for something other than the presence of variable.

Yes, that is my understanding. Variables in C are inextricably linked to memory locations, and either exist (by virtual of tying that name to the memory location in the first place) or they don't (in which case you have no variable name to test anyway). Variables will always have a value, possibly a bad value, and there's no fundamental difference between bad values that originate from improper initialization, and buggy/negligent code that explicitly assigned that bad value to the variable. Aside from types and sizes, which is again tied to memory considerations, C doesn't generally know or care whether a value is 'valid' or not – that's an abstraction left up to the programmer to implement.

Rudha seemed to imply a native solution for testing the validity/existence/whatever of a variable without these layers of abstraction, and I'm still not sure if that's due to me (and apparently others) misinterpreting what she said, or an incorrect assertion on her part, or finally an unknown part of the language that really does let you do this. If it's the latter I definitely would like to know about it. If it's either of the first two, then that's fine, cockups happen. Either way I'd like some feedback from her about this, even if it's only privately, since I'm really only interested in the technical bits and not who's right, wrong, or playing with strawdollsactionfigures.
28 Oct, 2010, ATT_Turan wrote in the 43rd comment:
Votes: 0
Runter said:
The best solution here is obviously an abstract datatype representing an account if you're wanting to do anything more fancy than track a single value.

Why wouldn't you just store the accounts of all the PC's in a hash grid? :wink:
28 Oct, 2010, bbailey wrote in the 44th comment:
Votes: 0
Runter said:
The best solution here is obviously an abstract datatype representing an account if you're wanting to do anything more fancy than track a single value.

I agree completely.
28 Oct, 2010, quixadhal wrote in the 45th comment:
Votes: 0
Just use ROM's extended bit flags and declare Yet Another Bit. Using YAB follow the established ROM protocol for making things cryptic and difficult to read in source. You could use #defines to make the new bit value be clear, but in practice people will just add the raw numbers together and do 12 tests in one comparison, to save 1 cpu cycle somewhere.

Also, if you're making a DBZ game for ROM, your bank account may need to use at least 512-bit integers to handle the number of coins collected. You might be able to save some space though, by just having an implicit multiplier of 9001.
28 Oct, 2010, David Haley wrote in the 46th comment:
Votes: 0
bbailey said:
Yes, that is my understanding. Variables in C are inextricably linked [… other things …]

Everything in this paragraph is correct, yes.

Regarding your second paragraph, and methods of testing this stuff, MSVC gives you a compile-time method of checking the existence of a variable. "Existence" in this context refers to what you said in your first paragraph: actually having a name for some location in memory, or a function, or something. The MSDN page for __if_exists gives some examples of how you might use it. Note that none of it is useful for runtime checks.

A brief search shows that as of mid-2009 at least, g++ doesn't support __if_exists. To be honest I'm not convinced it's a hugely useful construct in the first place, but, well, that's another story and just my ol' personal opinion based on not having needed it so far. I'm sure it's useful in some contexts.

Some might define "existence" as something like: "does it have an initialized value?" The problem is that this is also, according to the language, and as you said as well, Bobby, undefined. It's true that some implementations in some circumstances use a special value to indicate that a value hasn't been initialized. I think that MSVC in debug compilation uses 0xcdcdcdcd or something like that for uninitialized pointers? Well, anyhow, any behavior here is implementation-dependent, and furthermore, implementation-mode-dependent, so it's hard to advise relying on this method. Besides, if you use the indirection of a pointer – and yes, I agree with Runter that this is not an ideal solution and a proper data structure is better, anyhow – the indirection of a pointer solves this problem for you by distinguishing between (a) whether or not you point to a value, and (b) whatever that value might contain (if there is one to point to).

The problem here, really, is that asking about the "existence" of a variable in C/C++ is something of an odd question in the first place. As you said earlier, either you have a name for something (hence it exists) or you don't. There is perhaps an interesting case of something existing (because it was allocated) but you have no reference to it – in other words, a memory leak. But this is not a hugely interesting case (other than for eliminating memory leaks) because you can't do anything with the memory in question anyhow. In any case, I'm not completely sure how such a construct could exist at runtime, because it's not clear to me in the first place what asking this question even means. If I've defined the variable in my data structure, then I have it (its value is another question). If I don't have it defined, then I don't have it.

This is quite different from languages like Ruby, Python, Lua, etc., where you can add/remove attributes to objects/tables on the fly, and even implement functions that determine, dynamically at runtime according to whatever criteria you desire, whether or not an attribute exists. In this context it makes complete sense to talk of the existence of some name on some object, because it might or might not be there – and if it's there, it might or might not have a value. (Interestingly, in Lua, there is no way to distinguish between t.foo being missing or nil; if t is a valid table, then t.foo is either the relevant value, or nil if t has no field 'foo'. The Lua authors respond that 'nil' means 'missing', so this is in fact exactly the desired behavior. It merely means that you cannot store a 'nil' as an explicit value.)

It's worth noting that you can implement a pseudo-dynamic-language approach here without going crazy with reimplementing Python or Perl or whatever. You can store your own attribute map from attribute name to attribute value. Then, testing for the existence of an attribute takes on the same character as it does in dynamic languages: you have it, at runtime, if it's in the map; if it's not, you don't have it. But this is not a test that the C language provides; this is a semantic relationship that you implement on top and it is not testing 'variables' per se.

I think it's an interesting conversation though with the potential to be very educational, if there is in fact some way of testing all of this at runtime, or a portable method for testing for uninitialized variables. If anybody has light to shed there I would very much appreciate it.

ATT_Turan said:
Why wouldn't you just store the accounts of all the PC's in a hash grid? :wink:

I see what you did there. :blues:
28 Oct, 2010, Runter wrote in the 47th comment:
Votes: 0
In Ruby all instance variables are nil whether defined or not. The distinction is that in ruby you must define an accessor of some kind to access them. So actually you may throw the no method exception from the outside. But that's only a consequence of needing the accessor.
29 Oct, 2010, quixadhal wrote in the 48th comment:
Votes: 0
Also, in Ruby (as in Python and Perl, and probably most modern dynamic languages), nil is distinct from the numeric value of 0. In C, a "NULL" pointer is really just a pointer to memory location 0. In *MOST* cases, this isn't a legal value for a pointer, but if you're doing low level OS work, it might be!

The problem stands out worst in a case like our bank account balance. If all you have is an integer describing the current balance, you are free to define 0 as meaning "no account", but by doing so you make it impossible for players to have empty accounts. You could shift the problem aside by declaring that -1 means no account, but by doing so you disallow negative balances (debts).

It's not really that big a deal to just declare an extra variable if you want existence checked. If you wanted to do things the Diku way, you could also make a "bank account struct" and use their linked list systems to tie it to the player object. That would make it easy to have multiple accounts at different banks, for example.