• 52T (unregistered)


    How does code like this even get past "does it run?" testing?

  • Dave Mays (unregistered)

    Smells like deliberate obfuscation.

  • Smells Like ... (unregistered)

    C

  • Mr. Operator (unregistered)

    Seems like somebody forgot the difference between ^ and pow()

  • Ryan Farley (unregistered)

    "It's not how big it is...it's the context in which you use it"

    Can I get that on a T-Shirt? Hehe.

  • black (unregistered)

    WTF?!?!?

  • Hexy (unregistered)

    This is definitely one of the bigger WTFs I've seen in a while. It's fairly obvious they're trying to use the built-in x^y operator (which doesn't exist in C/C++). But this example also demonstrates why you should enclose most macros in parentheses because of unexpected operator precedence. But if you're using C++, you might as well just use a constant:

    const int v = pow(2, sizeof(SpaceId)) - 1;

  • Ian Bicking (unregistered)

    ((1 << sizeof(SpaceID))-1) would also work.

  • Guayo (unregistered)

    nice one...
    I think it's a double WTF because as someone already said it, it seems that they are confusing pow() with ^.
    And also it's a WTF for not considering of operator precedence.

  • WanFactory (unregistered)

    My operator precedence is a little rusty, but here's a stab at these crazy evalutions based on 2^4-1

    (2^4-1) becomes (2^3) becomes 1
    2^4-1==1 becomes 2^3==1 becomes 2^0 becomes 2
    1==2^4-1 becomes 0^3 becomes 3
    1+2^4-1 becomes 3^3 becomes 0
    2^4-1+1 becomes 2^4 becomes 6
    2^4-1*5 becomes 2^-1 becomes -3

    this is just made my day

  • josh (unregistered)

    Well... technically x^y does exist, it's just not exponentation.

    ((1 << sizeof(SpaceID)) - 1) will work, but it's not right. First, (1 << sizeof(SpaceID)) will overflow. The compiler will probably give you 0 instead, but that's undefined behavior so it doesn't have to. Then the whole thing is -1, which is actually kinda small for an int.

    If you made that 1 unsigned (1u), then you're guaranteed to get zero (assuming sizeof(SpaceID) == sizeof(unsigned)), but subtracting 1 gives you UINT_MAX, which won't fit in an int. Usually the compiler would give you -1 here as well, but that's also undefined behavior.

    If SpaceID really is a typedef to int, you should just use INT_MAX. (or -1, if that's truely what you want. but then I suspect typedef unsigned SpaceID; and UINT_MAX is better.)

    pow would also work, but it's not a compile-time constant because of the function call (even if you're compiler's clever enough to do it at compile time), so there are places where you can't use it. And if you're compiler is less clever, it's not a good habit to do things at run time that can be done at compile time.

  • Dare (unregistered)

    Josh: Why would (1 << sizeof(SpaceID)) overflow? If SpaceID is defined to be an int, then sizeof(SpaceID) is 4.

  • J.p. (unregistered)

    It wouldn't overflow, but it also wouldn't give the right answer. Bit shifting is multiplication by two, not exponentiation. Shift 4 to the right, you'll get 8. 8-1 = 7. Right?

  • 5pvps (unregistered)

    J.p.: No, shifting 4 to the right would get you 16. Each place shifted over is a multipication by two. Since the base in this exponentiation is 2, then there's no difference -- multiplying by two n times, or putting the base to the power of n.


    1 << 4 == 1 * ( 2 * 2 * 2 * 2 ) == 1 * pow ( 2, 4) == 16.

  • xyz (unregistered)

    ROTFL... assuming he wanted to do pow() exponentiation, and do it right, anyone got that MAX_PID = 15 ?

    If PID is ProcessID (otherwise this is another WTF), it isn't a very small number for a maximum ?

  • Voblia (unregistered)

    Bwahahah it's 3 in one - the guy is trying to get a max int yet he doesn't know he is geting size in bytes not bits!

  • necroyeti (unregistered)

    ahhh, thx, that's a real WTF, and definitely one of the best ever :) Now I just like to know at how many places in the code this BS was used.

  • somormujo (unregistered)

    Good catch Voblia,

    even better to think about having something like:

    #define MAX_PID 2^sizeof(SpaceId)^8-1 //SpaceId is typedef int, sizeof(int) is 4

    Hahahaha

  • Lothar (unregistered)

    Voblia: The author of the code knew the effect of sizeOf, otherwise the comment
    > //SpaceId is typedef int, sizeof(int) is 4
    wouldn't make sense.

  • Warp (unregistered)

    A WTF in these comments: People are writing the "shift to left" operator<<, but saying "shift to the right".

    (Shifting to the right by 4 (ie. value>>4) divides the value by 16.)

    Can't coders distinguish left from right?-P

  • JD (unregistered)

    I figured the comment was put in not by the original coder, but by the submitter so we wouldn't all be going "well WTF is SpaceID anyway?!?!??!?!?!".
    A clarification, Alex?

  • Henrik A (unregistered)

    JD - That's correct, I put that comment there.

    I'm glad you guys like it! This has probably got to be the single worst line of C I've ever seen. :)

  • Lothar (unregistered)

    Henrik A: You're right, the WTF per line ratio is optimal here.

  • Evan M (unregistered)

    Alright, in this guy's defence, if the ^ operator actually did powers, and instead, we replace it with the pow() function, then the order of operations is fine.

    However, the use of sizeof() is wrong twice. First, you have the byte vs. bit idea. But the other failure that we have here is the fact that he doesn't consider negative numbers at all. The max value of an int is pow(2, (32 -1)) - 1. Now that's a major wtf error.

  • Ghetto Pimp (unregistered)

    cocky sumbitch, that Evan

  • fluffy (unregistered)

    And anyway, pow() returns double, which is stupid and inefficient and can also lead to roundoff errors (granted, not in this situation, but still). Just use 1<<x instead.

  • Mike R. (unregistered)

    re: It's not how big it is ... 10/22/2004 5:35 AM Warp



    ... Are you the same Warp as in the POV forums?
  • Oliver Klozoff (unregistered)

    This same problem occurred on a in-house system:

    Our company, before I was hired, needed to find a way to generate something like a four-digit "hash" from another number.

    Rather than take a secure hash algorithm, like SHA or MD5 (or hell, even MD4 or MD2) and work from there, they rolled their
    own, involving crazy things like
    floating point multiplication and sprintf. And since all they knew was VB, they wrote the sample algorithm in VB.

    At the very end, the algorithm would run an extra loop if the following test failed:

    hashValue < 10^(hashDigits - 2)

    In case it's not immediately obvious, this basically checks if hashValue is less than 100 -- if it is, it runs again. The idea was to make sure the hashValue had at most one zero at the beginning.


    Fast forward: This algorithm was then sent to a developer writing a program for a small hardware device (about the same size as a credit card terminal). This developer knows C (the language most often used for the CPUs of those devices), but not Visual Basic. Fortunately, as some of you may know, VB is very easy to understand by a programmer who knows another language. And for the stuff that he didn't get, he could ask us.

    Has anybody guessed where this is going yet?

    The last line -- the one attempting to see if there were too many digits -- was copied exactly... Changing the meaning from 'hashValue < 100' to 'hashValue < 8'.

    For an added bonus, the hardware device has no floating-point unit -- the floating point math is 64-bit software emulated. Which means that, due to rounding, the 80-bit FPUs in our x86 desktops sometimes generated different hashValues than the hardware device did.

    To top it all off: When I actually went back and analyzed the algorithm -- about 30 lines of code -- I discovered that it reduces to 1 line of C, involving four 64-bit integer multiplies.

    How's that for WTF?

  • foxyshadis (unregistered)

    Psst, fluffy, read the comments before you post.

    It seems this is all way way too much work. Just #define this as INT_MAX, UINT_MAX, or whatever number you need, on the line after the typedef. That way you don't have to play games to get the value (and still get it wrong), and always remember to change it. Given the utter disregard the C spec has for type standards of any kind, this seems to be the only safe way to do it. (Short of defining everything as a long long and assuming there's a snowball's chance in hell of generating a value over 18 quintillion in 32-bit operations. If that's still a problem, there are 256-bit integer math libraries out there. laughs)

  • Hartmut (unregistered)

    I don't do any programming in C, but given the discussion above and the example that Oliver gave, wouldn't the expression "hashValue < 10^(hashDigits - 2)" end up meaning "(hashValue < 10)^(hashDigits - 2)" in C? The two possible outcomes are 0^2, which comes out to 2, or 1^2, which comes out to 3. In both cases, the end result is non-zero, which means the test would be logically equivalent to "if (1)".

  • peter beaguely (unregistered)

    id base my site/job security on techniques like this. fucking awesome.

  • Pendant (unregistered)

    You shouldn't enclose macros in parenthesis. If you don't, then they'll never work as expected and people will actually read them before using them. And reading a macro before using it is what everyone should do.

    Plus, you'll end up with people on your team who code (in C++) things like

    if FAILED(hr == pInterface->DoSomething())
    {
    }

    and think they're just fine. After all, it compiles.

Leave a comment on “It's not how big it is ...”

Log In or post as a guest

Replying to comment #24886:

« Return to Article