On Thursday, 28 March 2013 at 20:03:08 UTC, Adam D. Ruppe wrote:
I was working on a project earlier today that stores IP addresses in a database as a uint. For some reason though, some addresses were coming out as 0.0.0.0, despite the fact that if(ip == 0) return; in the only place it actually saves them (which was my first attempted quick fix for the bug).

Turns out the problem was this:

if (arg == typeid(uint)) {
        int e = va_arg!uint(_argptr);
        a = to!string(e);
}


See, I copy/pasted it from the int check, but didn't update the type on the left hand side. So it correctly pulled a uint out of the varargs, but then assigned it to an int, which the compiler accepted silently, so to!string() printed -blah instead of bigblah... which then got truncated by the database, resulting in zero being stored.

I've since changed it to be "auto e = ..." and it all works correctly now.



Anyway I thought I'd share this just because one of the many times bearophile has talked about this as a potentially buggy situation, I was like "bah humbug"... and now I've actually been there!

I still don't think I'm for changing the language though just because of potential annoyances in other places unsigned works (such as array.length) but at least I've actually felt the other side of the argument in real world code now.

IMHO, array.length is *the* place where unsigned does *not* work. size_t should be an integer. We're not supporting 16 bit systems, and the few cases where a size_t value can potentially exceed int.max could be disallowed.

The problem with unsigned is that it gets used as "positive integer", which it is not. I think it was a big mistake that D turned C's "unsigned long" into "ulong", thereby making it look more attractive. Nobody should be using unsigned types unless they have a really good reason. Unfortunately, size_t forces you to use them.


Reply via email to