View Full Version : Unsigned floats supported in C++
Sharkbait
12-11-2005, 05:18 PM
I've scoured the net for a solution to a problem I'm having but to no avail and I'm hoping that some kind knowledgable soul on Indiegamer might help me out:
I have some dimenions defined as 'unsigned float' since they are meant to describe positive, but possibly fractional sizes. The trouble is that unsigned floats seem to work like unsigned ints, that is, they truncate the fractional part of the numbers assigned to them!
For example,
unsigned float x = 2.9f;
yields a value of 2 in x. I also noted that code insight in VS 2003 shows the variable as an unsigned int!! Any idea of what's going on?
Thanks
Sharpfish
12-11-2005, 05:36 PM
The answer - while not perfect - is that you should use float, not unsigned float - if needs be then you can always FABS it if it goes negative?
<edit>
In fact - just checked my compiler (which I admit is old and I probably missed the whole "yes we can now use unsigned floats movement") but it complains if I try to use one.
Maybe VS2003 is "correcting" the "error" by casting it to int behind the scenes hence it showing you an INT. Can you not use a signed float for your needs? if it is not large enough what about "double"? - maybe the crapola still present in VC6 (my tool) is still in VS2003 and is allowing you to define it but is bodging it up behind the scenes?
2nd edit - realising the above is as clear as mud. What I am trying to speculate is that perhaps in the same way VC6 is preventing an unsigned float being used, VS2003 is auto-correcting it to it's own (MS meglomanical) standard without telling you? and having never used an "unsigned float" myself, I wasn't even aware they were valid?
AlexN
12-11-2005, 11:08 PM
unsigned can only be used on integral types. All floating point types contain sign-bit, and use IEEE 754 standards. So, unsigned can't be used on floating point.
Sharkbait
12-12-2005, 01:04 AM
In the meantime I decided to actually take heed of the compiler warnings.. and I noticed that every 'unsigned float' is marked with a warning and converted to 'unsigned int'.. which goes to show that developing an immunity to c++ warnings is not a good thing, nor is coding in the early morning hours! :rolleyes: I'll have to weed out the "unsigned" floats and apply clamping as necessary.
Thanks guys!
MadSage
12-12-2005, 03:04 AM
I thought I was about to learn something new when I saw this thread. Unsigned floats?!! Never heard of them :D
Sharkbait
12-12-2005, 03:10 AM
Up to yesterday I took for fact that unsigned floats were supported in c++ and that they were essentially IEEE 754 floats automatically clamped by the compiler to zero or positive values. The really odd thing is that the compiler does not issue an error but simply a warning and quietly converts them to unsigned ints. Ah well.. on the plus side (no pun intended) I learned something new...
mahlzeit
12-12-2005, 03:24 AM
Compilers often have different warning levels. It's smart to always set it to the highest level possible, so these things won't escape notice. If necessary, you can disable harmless warnings with a #pragma statement, so they won't clutter the compiler output.
MadSage
12-12-2005, 04:24 AM
I think it's good practice to fix all warnings - don't just ignore them. As soon as I see a warning, I fix it. The only warning I ever disable is the zero sized array warning, because I often use zero sized arrays at the end of packet structures (being a network programmer most of the time). In that case, I place a pragma to disable the warning right before the array declaration, and re-enable the warning on the following line - just in case I accidently declare a zero sized array elsewhere! I think re-enabling warnings in that way is also good practice, if you really must disable a warning. In my zero sized array example, it's unavoidable.
Fabio
12-12-2005, 05:57 AM
But zero-sized arrays (which I also find very useful) cannot be declared if they're in a struct/class that later will be inherited, right? (i.e. in a base class)
In ANSI C++ you can't actually instantiate such a structure, if I'm not mistaken. Example:
struct MyBaseClass {
char * Name;
int Properties;
int Flags;
int Size;
unsigned char Data[0];
};
works as long as you then don't use it to create another struct/class, e.g.:
class MyDerivedClass : MyBaseClass {
int AddedStuff;
};
The above generates an error, not a warning.
Which I find an annoying limitation. It would be perfectly justified because while inheriting, it's not possible to know where to add the new stuff if there's an unknown-size object before. But I want it as a label, so it would be perfectly doable in the specific, [0] size case (you see, I inherited my programming style from assembly). Of course it would be impossible in a [] case (I'm talking syntactically here, unfortunately for C/C++ [] and [0] seem to be the same thing, but they shouldn't really).
Is there a fix or a serious workaround for this? Even if it's not perfectly ANSI C++ compliant. BTW: putting [0] instead of [] as I mentioned doesn't help. Neither the use of void (I had to try ;) ). Labels can't be declared there. What a disappointment.
Actually the way I work around it is annoying too:
I remove the "unsigned char Data[0];" part from the BaseClass, and add it to the derived class. But since Data needs to be used by members of BaseClass (that's what I want in the end, otherwise the whole OO of C++ becomes the thing to fix everywhere), I access the Data via a pointer to BaseClass+sizeof(BaseClass), eventually casted to a pointer to the derivedclass when I want to pass it to a function that accepts that type. Ugly, but as I said I like to think in asm-like terms.
MadSage
12-12-2005, 06:19 AM
None of the classes I use zero sized arrays in are inherited, so I can't comment. I've never tried it.
ggambett
12-12-2005, 07:29 AM
I think it's good practice to fix all warnings - don't just ignore them. As soon as I see a warning, I fix it.
Exactly. You shouldn't consider your code done until it compiles cleanly. It's only good for you. It's not hard to keep it that way if you start from scratch and fix warnings as soon as they appear. If you already have a big codebase it could be painful at the beginning but I'm convinced it's good in the long run.
FlySim
12-12-2005, 08:30 AM
Usually Im a fairly lazy coder, but I do fix all my warnings.
For example, this warning is really helpful and I would hate to miss it:
a == 23.0;
something like "This statement did nothing, did you mean it?"
Sharpfish
12-12-2005, 08:54 AM
I am always concerned with warnings and correct them as I go.. but usually you know why they are there. The = / == is always a gotcha that can slip in no matter how diligent you are though.
Jim Buck
12-12-2005, 09:57 AM
Wow, and I thought it was standard practice to enable "treat warnings as errors". Has saved my butt on too many occasions to count.
Escotia
12-12-2005, 11:15 AM
The = / == is always a gotcha that can slip in no matter how diligent you are though
You can reduce the likelyhood of this error a little by always placing constant values ahead of variables in an equality test
ie. if(23.0 == a)
if you then leave yourself an = short you get
if(23 = a)
which shouldn't compile.
As FlySim points out, if you get an assignment wrong and add an extra = then you get a nice warning, so that only leaves equality tests between variables (unavoidable) and assignments inside boolean comparitors, which can usually be avoided by doing the assignment outside.
Sharpfish
12-12-2005, 11:23 AM
You can reduce the likelyhood of this error a little by always placing constant values ahead of variables in an equality test
ie. if(23.0 == a)
Yeah i've seen that tip before (somewhere) and tried it for a while, to be honest it ONLY slips through (for me) occasionally and I prefer to do it the usual way (keeps my sense of "neatness" happy I suppose ;).
The above way is definitley nice if you suffer from it a lot though.
vBulletin v3.6.0, Copyright ©2000-2008, Jelsoft Enterprises Ltd.