Just when you thought stupidity had reached its limits (a debugging rant)

Started by
31 comments, last by Way Walker 15 years, 4 months ago
I just spent the best part of two hours wondering why my code breaks apparently arbitrarily. Eventually I boiled it down to this:

		int tmp = -8;
		unsigned int tmp2 = 16;
		int tmp3 = tmp2/5;
		float a = float(tmp + tmp3);
		float b = float(tmp + tmp2/5);

This sets a==-5 and b==4.2949673e+009 *beats forehead against desk* For the last few years I've thought of myself as a fairly competent programmer, yet there's always a new lesson to learn. I just wasn't expecting a lesson like this. It's got something to do with unsigned vs signed integers, I guess. I still don't know if this is a C language subtlety I've overlooked, or maybe a bug in Visual Studio (I usually use gcc). Not sure if I want to find out. Thanks for letting me vent.
Advertisement
It's a signed/unsigned thing. When you do arithmetic between a signed int and an unsigned int, the result is unsigned. In this case, -8 is getting transformed into 0xFFFFFFF7, and tmp2/5 is 3, so the result is 0xFFFFFFFA, which is roughly 4.29 * 109.
yeah that is pretty gay although I always add a .0 to numbers when I want the float... thanks for sharing the lesson.

Did you fix it like this:

float b = float(tmp + int(tmp2)/5);
or
float b = float(tmp + tmp2/5.0);
That's way Java doesn't have unsigned. 90% of the C programmers don't get the signed/unsigned thing.
It always amazes me that otherwise competent programmers have such a stiffy for unsigned. Is that extra bit reeeeally worth losing so much assertability and running into so many more edge cases?
Quote:Original post by Sneftel
It always amazes me that otherwise competent programmers have such a stiffy for unsigned. Is that extra bit reeeeally worth losing so much assertability and running into so many more edge cases?


I find often the ability to have something signed can lead to bugs, especially when it makes no sense whatsoever, and only use signed variables when I know something could be negative. Often times I don't want my integers to be negative. Whether it be physical screen or logical client coordinates, an index, etc., the need to accomodate negative integers usually turns out to be a special case for me... I guess I just haven't really been burned by something not being signed when it should be (well I can recall one minor incident... so let's say I haven't been severely burned).
Quote:Original post by popsoftheyear
Quote:Original post by Sneftel
It always amazes me that otherwise competent programmers have such a stiffy for unsigned. Is that extra bit reeeeally worth losing so much assertability and running into so many more edge cases?


I find often the ability to have something signed can lead to bugs, especially when it makes no sense whatsoever, and only use signed variables when I know something could be negative. Often times I don't want my integers to be negative. Whether it be physical screen or logical client coordinates, an index, etc., the need to accomodate negative integers usually turns out to be a special case for me... I guess I just haven't really been burned by something not being signed when it should be (well I can recall one minor incident... so let's say I haven't been severely burned).


I think the caveat here is twofold:

1) The ranges restrictions in most languages are seriously underwhelming. Signed vs. unsigned. 16 bits vs. 32 bits. In reality, we want ranges for all sorts of things. Percents can be valid between 0 and 100. Perhaps hit points is valid between 0 and 9999 (Square). What we really want is a better built-in way to define ranges.

2) Converting between types which have different ranges automatically is error prone.

Of course, in C++, you can provide functionality like this with templates, but having it built-in, ala Ada would be really nice. It's a shame that as much as modern languages have lifted off predecessors that they missed that one.
Quote:Original post by popsoftheyear
I find often the ability to have something signed can lead to bugs, especially when it makes no sense whatsoever, and only use signed variables when I know something could be negative.

Yeah, this is always the thinking, and it is totally wrong. Using unsigned integers won't prevent the "accidentally negative" bug. It'll just transmute it into the "accidentally really big" bug, which is far more difficult to diagnose. Don't want negative numbers? Throw in some assertions.
So in that case what's wrong with just testing if something is too big? If I'm checking bounds, instead of asserting x >= 0 as well as x <= max, I just assert that x <= max. I just don't see the harm, but I have the benefit of knowing things like "hey whatever parameter I pass to this function needs to be a positive integer". If I'm working out some sort of math, 99 times out of a hundred I need more accuracy than a whole number any way, and I am going to be using floats. I still can't see (said the guy with maybe just 1 eye but he's not quite sure)
Quote:Original post by popsoftheyear
I need more accuracy than a whole number any way, and I am going to be using floats.

More accuracy than a whole number, eh?
int i = 123456789;float f = i;std::cout << i << std::endl << std::fixed << f << std::endl;

This topic is closed to new replies.

Advertisement