• St Mary's Hospital for all Kinds of Wheels (unregistered)

    I don't know this programming language.

    Did the Senior Programmer invent it?

  • (cs)

    I wrote this comment, therefore it is good enough.

    All of your comments will need to be rewritten.

  • (cs) in reply to TheRealFoo
    TheRealFoo:
    Otto:
    TRWTF is that either of those functions exists at all.

    Double comparison: Are > and < and = not good enough for you?

    As "Don't get it" pointed out, that asm comparison has two properties those operators do not: It is a 3-way comparison instead of a boolean one, and it can handle NaN values without throwing an exception.

    If you need that, then the operators are not good enough indeed.

    If this is C or C++ (and I'm quite sure it is), comparing NaN does not throw exceptions, it simply returns false for any comparison; heck, C doesn't even know about exceptions.

    Also, I doubt you need an assembler function for the rare cases where you need 3 way comparison without doing an if/else right behind anyway.

  • (cs)

    I used to work with a girl like that. She wrote every single thing she needed for any project. She would never read or write any documentation and her libraries had all kinds of quirks that made a nightmare to use them.

    Example: 2 different functions that happened to return strings, one of them demanded that the string was pre-allocated by the caller but the other allocated the string itself so we would have to delete it later. And this was random, no valid reason was ever given.

    She never delivered a project on time. Strangely the boss trusted her and always nominated her to lead all projects. And I can't see why, because she was so very NOT hot!

  • Mike Dimmick (unregistered) in reply to Steve
    Steve:
    confused:
    Maybe it's too early in the morning, but what's with the !strcmp part? It seems like it'd work the same way without the ! since if the strings are equal, strcmp returns 0 and !0 is still 0.
    !0 is 1
    !0 is non-zero. It is not necessarily 1. C says 0 is treated as false, but any other value is true. The compiler is allowed to generate or use any value it likes.

    C++ says non-zero coerces to true while zero coerces to false. Strictly, the type of the expression in a controlled statement (if, while, etc) is bool in C++, int in C. I can't remember if C++ standardizes the result of (int)true, or whether it's left implementation-defined.

    You may well find that your compiler does produce 1 in debug builds, but in optimized release builds, it may be some other value depending on the expression.

    Anyway, don't do any mathematical expressions relying on the value of truth. You will get some unexpected answers.

  • Jason (unregistered)

    Let's see..."If I didn't write it, then it must suck.", "If the project doesn't have my code in it, then it must suck.", and "We have to get this project done RIGHT NOW." I may have worked with people like that before...

  • a pedant (unregistered) in reply to Mike Dimmick
    !0 is non-zero. It is not necessarily 1. C says 0 is treated as false, but any other value is true. The compiler is allowed to generate or use any value it likes.

    C (at least) does say the !0 is 1, in section 6.5.3.3 of the standard, paragraph 5:

    The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0.

    But of course you're right to say that using the numerical value of truth in arithmetic is not nice.

  • Henning Makholm (unregistered) in reply to Don't get it
    Don't get it:
    I don't understand the business with checking "ah", as FUCOMI does not modify ah. Maybe you left out a LAHF instruction that was in the original code?
    Not LAHF, but FSTSW AX. The FPU flags are separate from the ordinary ones.
  • CNinja (unregistered) in reply to mxx

    [quote user="mxxIf this is C or C++ (and I'm quite sure it is), comparing NaN does not throw exceptions, it simply returns false for any comparison; heck, C doesn't even know about exceptions.

    Also, I doubt you need an assembler function for the rare cases where you need 3 way comparison without doing an if/else right behind anyway.[/quote]

    It's C++

  • Jay Smith (unregistered)

    My apologies for the confusion, this was written a few weeks ago and I didn't check back to see if it was up.

    These are two different examples. I guess that could have been made more clear. One for double comparisons one for string comparisons.

    The WTF being rewriting code that is unnecessary and slower than what the average bear would do. The double check is roughly 10 times slower than letting the compiler optimize a standard if else if else check.

    This is what happens when good programmers go unchecked.

  • fluffy777 (unregistered) in reply to Code Dependent
    ...hissy fits ensue complete with resultant silence treatment.
    If the developer was female, this would be a hussy fit.
    ... and if the developer was effeminate, this would be a sissy fit.
  • biziclop (unregistered) in reply to Don't get it
    Don't get it:
    It not only does a 3-way compare, but the special FUCOMI instruction is the only compare instruction that does not raise errors if the numbers are undefined (NaN).

    Fucomi, is it only me or does it really sound like a Japanese developer trying to swear in English.

  • Dan (unregistered) in reply to Don't get it
    Don't get it:
    There's nothing wrong with the double_compare code, except maybe a lack of comments.

    It's doing a kind of compare you just can't do in C.

    It not only does a 3-way compare, but the special FUCOMI instruction is the only compare instruction that does not raise errors if the numbers are undefined (NaN).

    If you absolutely had to write this in C it would be along bit of code, something like:

    if( IsNan( A ) || IsNan( B ) ) return 0xC0003; else { Diff = A - B; if( Diff < 0.0 ) return 0xC0002; else if( Diff > 0.0 ) return 0xC0001; else return 0xC0004;

    I've done similar asm shortcuts, but only like in the inner loop of a sort routine that was called a bazillion times.

    I don't understand the business with checking "ah", as FUCOMI does not modify ah. Maybe you left out a LAHF instruction that was in the original code?

    Which adds to the WTFery. 1) The compiler can't optimize this function because it's already been written in stone--er, ASM. 2) The function performs 2 memory loads and then a store. If you've seen the NS-EEL library for Winamp's visualizers, you would recognize this kind of "generic function" programming. It is several times slower than what an optimizing compiler would produce using knowledge of context and machine tricks. 3) Wanna bet this function is called in a tight loop? 4) Why even mess with AH? There are ASM conditional jump instructions that can already do everything he wanted to do, without that AH test. So if that's the function as it really is, then it's not only slow, it's wrong. If there is a missing LAHF, then the function is even slower than it should be.

  • antred (unregistered) in reply to SatanClaus
    SatanClaus:
    STL sucks. It rightly should be called non-STL. You better test it well!

    Errr what?? Unless you use a totally broken compiler / STL implementation, STL (or SC++L as it's called now) is the way to go.

  • Anon. (unregistered) in reply to valerion
    valerion:
    I wrote this comment, therefore it is good enough.

    All of your comments will need to be rewritten.

    First! All of your comments have been superseded. captcha: venio, how appropriate!

  • Crabs (unregistered) in reply to confused
    confused:
    Maybe it's too early in the morning, but what's with the !strcmp part? It seems like it'd work the same way without the ! since if the strings are equal, strcmp returns 0 and !0 is still 0.

    Turn in your programmers guild card immediately.

  • (cs) in reply to fluffy777
    fluffy777:
    ...hissy fits ensue complete with resultant silence treatment.
    If the developer was female, this would be a hussy fit.
    ... and if the developer was effeminate, this would be a sissy fit.
    If he'd been chugging 'em down at a pub for a few hours, it would be a pissy fit.
  • (cs) in reply to antred
    antred:
    SatanClaus:
    STL sucks. It rightly should be called non-STL. You better test it well!

    Errr what?? Unless you use a totally broken compiler / STL implementation, STL (or SC++L as it's called now) is the way to go.

    I second that. Try and write something faster than the STL libraries - I'll stick with the highly optimised, better-than-anything-I-can-dream-of-writing, library code :)

  • (cs)

    The only justification for the StringUtil_Compare function that I can fathom is the old "fortify your subsystems" strategy that Steve McGuire espoused in "Writing Solid Code." You can guard yourself against any bugs in the libraries, you can add counters if you want to look for memory leaks, etc.

    However, that's usually done using #DEBUG directives, and the release versions generally call the libraries directly.

    Plus if he's the sort to throw hissy fits, then it's more an ego thing, not a coding-practices thing.

  • Anon (unregistered) in reply to trincanapera
    trincanapera:
    I used to work with a girl like that.

    Pictures or it didn't happen! There are no girls in IT. ;)

  • Anon (unregistered) in reply to Code Dependent
    Code Dependent:
    fluffy777:
    ...hissy fits ensue complete with resultant silence treatment.
    If the developer was female, this would be a hussy fit.
    ... and if the developer was effeminate, this would be a sissy fit.
    If he'd been chugging 'em down at a pub for a few hours, it would be a pissy fit.
    If he'd been spinning around on his chair, it would be a dizzy fit.
  • Loris (unregistered)

    http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918

    Sorry, I just had to post this link :)

  • n (unregistered) in reply to Steve
    Steve:
    confused:
    Maybe it's too early in the morning, but what's with the !strcmp part? It seems like it'd work the same way without the ! since if the strings are equal, strcmp returns 0 and !0 is still 0.

    !0 is 1

    strcmp returns 0 when the strings match. The function wants to return 1(true) if the strings match, so you can do return !strcmp(left,right);

    However, I find that ! in the above case is "confusing" because personally I only use ! for inverting a boolean type value. strcmp on the other hand returns either <0, 0 or >0 depending on the comparsion, so I find it clearer in this case to write return strcmp(left,right) == 0;

    Yes, the ! operator is doing a boolean evaluation of the integer that it was passed, so 0 becomes true (1) and any other number becomes false (0). This is a nice legacy of C not having a actual boolean type.

    Yes, just using the actual equality operator is much clearer to me as well.

    #include <stdio.h>
    
    int main(char ** argv, int argc) {
            char * str1 = "Testing1";
            char * str2 = "Testing2";
    
            printf("%d\n", strcmp(str1, str1));
            printf("%d\n", strcmp(str1, str2));
            printf("%d\n", strcmp(str2, str1));
    
            printf("negated\n");
            printf("%d\n", !strcmp(str1, str1));
            printf("%d\n", !strcmp(str1, str2));
            printf("%d\n", !strcmp(str2, str1));
    
            return 0;
    }
    

    Compiled with:

    ~ $ gcc --version
    gcc (GCC) 3.4.6 (Gentoo Hardened 3.4.6-r2 p1.5, ssp-3.4.6-1.0, pie-8.7.10)
    Copyright (C) 2006 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

    Results in:

    0
    -1
    1
    negated
    1
    0
    0
    
  • (cs) in reply to Loris
    Loris:
    http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918

    Sorry, I just had to post this link :)

    I can believe that "senior programmer" == Linus Torvalds here. He's full of it.

  • soup (unregistered) in reply to Archimidas
    Archimidas:
    DemonWasp:
    Archimidas:
    I would rewrite that function as well, tho maybe not using assembler.

    No you wouldn't. You'd remove it and replace all instances in the codebase with the call to the built-in comparison function. You would do this because you are a competent professional.

    And then you would weather the hissy fit.

    I'd rewrite it so I didn't have to search the codebase and replace them all - the inlined function should essentially take care of that for me. It can sometimes be easy to miss some (embedded in pre-processor macros, certain build configurations etc.).

    THEN I'd throw a hissy and stop anyone using that damn function ever again.

    I don't know about that. That approach leaves cruft in code base. Why not just delete the function and fix all places where code doesn't compile if you are worried about missing something?

  • Ronuk (unregistered) in reply to Vollhorst
    Vollhorst:
    !0 == 1 0! == 1 !0! == ??? ;)
    Well, depending on precedence, !0! can still be defined (in C at least).

    (!0)! = 1! = 1 !(0!) = !1 = 0

  • Jay (unregistered) in reply to Mike Dimmick
    Mike Dimmick:
    Anyway, don't ... rely on the value of truth. You will get some unexpected answers.

    Wow, is he talking about software or is he trying to make a profound philosophical comment?

  • tengfred (unregistered) in reply to Anon
    Anon:
    trincanapera:
    I used to work with a girl like that.

    Pictures or it didn't happen! There are no girls in IT. ;)

    http://xkcd.com/322/

  • (cs)

    For God's sake, will you all stop saying that !0 = 1. Everybody knows that it is. The poster questioning it was suffering from pre-coffee coffee deprivation and admitted so. So that's it, OK? You don't have to keep repeating that !0 = 1 in hopes that it makes you look knowledgable.

    There, look what you made me do. I said it twice. Happy now?

  • (cs) in reply to Smash King

    Can we rewrite the comments the same way?

    Before:
    Ah our dear friend NIH syndrome is back. I wonder how many good articles we read only because it exists?
    After:
    Oh, it was alright, but the duck could have been more salty. And it needs less wheels.

  • Andrea S. (unregistered) in reply to Don't get it
    Don't get it:
    There's nothing wrong with the double_compare code, except maybe a lack of comments.

    It's doing a kind of compare you just can't do in C.

    It not only does a 3-way compare, but the special FUCOMI instruction is the only compare instruction that does not raise errors if the numbers are undefined (NaN).

    If you absolutely had to write this in C it would be along bit of code, something like:

    if( IsNan( A ) || IsNan( B ) ) return 0xC0003; else { Diff = A - B; if( Diff < 0.0 ) return 0xC0002; else if( Diff > 0.0 ) return 0xC0001; else return 0xC0004;

    I've done similar asm shortcuts, but only like in the inner loop of a sort routine that was called a bazillion times.

    I don't understand the business with checking "ah", as FUCOMI does not modify ah. Maybe you left out a LAHF instruction that was in the original code?

    The code doesn't have an FUCOMI in it, though. It has an FCOMIP, which compares the top two registers on the stack, then pops both and throws a floating point exception if either is NaN. It also pushes onto the stack twice (the two FLD instructions), but pops three times (two in the FCOMIP instruction, and again in the superfluous FSTP, which both stores a value when none was calculated, and stores it into an automatic variable that will go away as soon as the function returns. Also, I think this does not calculate a three-way compare correctly, since the superfluous AND AH,20h instruction will overwrite the flags before the JNZ instruction.

  • Greg (unregistered) in reply to Jones

    Actually, although it depends on the compiler, usually

    !0 != 1

    Most often, !0 is defined as MAX_INT (or something similar), so for a 16 bit system:

    !0 == 0xFFFF

    Much better to use the compiler defined TRUE and FALSE, or define your own as #define FALSE 0, and #define TRUE !FALSE and let the compiler decide what ! means and do the same thing every time.

  • Anonymous Coward (unregistered)

    WOW! This reminds me of that one XKCD about Little Billy Tables. OMG has anyone else seen that?!? LOLOLOLOLOL!

  • Euripides (unregistered) in reply to Smash King

    So he is basically a knight who says NIH. And we all know how to fight them: with the word IT.

    So tell him next time: "Ok, but we here in IT use standard functions."

  • Keybounce (unregistered) in reply to a pedant
    a pedant:
    C (at least) does say the !0 is 1, in section 6.5.3.3 of the standard, paragraph 5:
    The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0.

    But of course you're right to say that using the numerical value of truth in arithmetic is not nice.

    Have you ever seen code that says

    bool = !!var

    to force the value to be exactly 0 or 1? I have.

  • Just Another WTF (unregistered) in reply to Anonymous Coward
    Anonymous Coward:
    WOW! This reminds me of that one XKCD about Little Billy Tables. OMG has anyone else seen that?!? LOLOLOLOLOL!

    Great! Thread closed... we are all done here and ready for the next one on monday.

  • (cs) in reply to St Mary's Hospital for all Kinds of Wheels
    St Mary's Hospital for all Kinds of Wheels:
    I don't know this programming language.

    Did the Senior Programmer invent it?

    Not enough people these days do. The reason I say this is that sometime someday people will be looking for a faster way. Those proficient enough with assembly will be able to tell you. That doesn't mean I'm encouraging assembly, because if you're going to write C code, you should stick to C unless for constraints you're in embedded systems and the only way to do something is assembly. However, if I gave you two functions, both one line of code, somebody with knowledge of assembly would be able to look at the generated instructions and give me a rough answer on which one will perform better and why.

  • (cs) in reply to CNinja
    CNinja:
    Funny thing is, that code wrongs several massive orders of magnitude slower than a simple if/else statement.

    Like base 5000?

  • (cs)

    Whatever happened to:

    if(someDouble <insert condition here> otherDouble) { }?

    Assembler or not, without some serious context that could possibly justify it, that function is ridiculous. Aside from the fact that it will actively defeat any attempts of the compiler to inline and optimize the compare, what's the point? You still now have to compare the result of the function against 3 possible return values!

    And WTF is up with "and ah, 20h?"

    1. the contents of ah are at unknown at that point in time
    2. setting eax overwrites what is in ah anyway as it's part of eax.
    3. In every single return path, eax is being set so the and ah,20h is completely useless and does nothing.

    Yea, definitely...WTF.

  • foo (unregistered)

    ; ; PWC - PRINT ; WITTY ; COMMENT ; ; E: - ; A: - ; ; ;

    PWC:

    CALL UP ; OS CALL!

    DEFM '#WITTY COMMENT STARTS' ; # = PRINT TEXT ; TEXT = WITTY COMMENT DEFB 13 DEFB 10

    NOP ; END WITH 0

    CALL UP DEFM '#PAY PER LOC RULEZ' DEFB 13 ; CR DEFB 10 ; LF NOP

    RET ; JUMP BACK

  • Iago (unregistered) in reply to Greg
    Greg:
    Actually, although it depends on the compiler, usually

    !0 != 1

    Most often, !0 is defined as MAX_INT (or something similar)

    We eagerly await the evidence you presumably intend to provide to support your assertion that "usually" compilers flagrantly violate the C standard.

    (You may be thinking of Microsoft Visual Basic, which does indeed define True as 0xFFFF, but is not in fact a C compiler.)

  • ultrapedant (unregistered)

    For the people wondering how a function that compares doubles has anything to do with a function that compares strings...

    Now, my ASM is a little rusty, but it looks to me like he's taking the pointer values to the strings as doubles. In other words, the new function is taking RAM addresses as parameters (in a very annoying manner). It's then comparing the values stored at those two RAM locations and comparing them.

    It also looks like some stuff might have been cut out during anonymizing.

    So, it probably works (for sufficiently small values of "work"), but I doubt that it works reliably.

  • Duke of New York (unregistered) in reply to Greg
    Greg:
    Actually, although it depends on the compiler, usually

    !0 != 1

    Most often, !0 is defined as MAX_INT (or something similar), so for a 16 bit system:

    !0 == 0xFFFF

    Much better to use the compiler defined TRUE and FALSE, or define your own as #define FALSE 0, and #define TRUE !FALSE and let the compiler decide what ! means and do the same thing every time.

    No. Just no. Go read the C standard for the ! operator (and all of the relational operators), and sin no more.

  • John Muller (unregistered)

    numerical values of truth...

    Back on the Commodore 64, I used to write expressions like:

    CL = (-20 * (INT(I/4) = I/4)) + (-20 * (INT((I+2)/4) = (I+2)/4)) + (-40 * (INT(I/2) = I/2))

    (might not be exactly correct, but the intent is to distribute items over four columns, exploting 'true' being -1, and 'false' being 0)

  • (cs) in reply to Zylon
    Zylon:
    Can we get an RMA for this WTF?
    The *pant* *pant* SLA *pant* for *pant* *pant* this *pant* WTF is *pant* six hours, *gasp* *pant* but it's still *pant* asking me for *pant* more blank tapes *koffspluttergasp* ...
  • (cs) in reply to TheRealFoo
    TheRealFoo:
    The XML parser bit in the article I understand. There is a ton of XML parsers out there, many bad, and the acceptable ones force specific structures upon your code that may or may not fit.

    I have yet to see a XML parser that is clean, fully standard-compliant and does not require you to overturn your data structures or code logic.

    (Links welcome.)

    So, that is the one part where I can understand why somebody might do that.

    Well, the introduction of XML into the mix was obviously a gratuitous invite to Wars O'Flame -- sheesh, an XML parser written from the ground up in assembler that'll only "work" on a 64-bit machine in the EN-US locale, what a concept... but only slightly worse than one built to work in Phuket -- but since you ask, here's a link. At least it's C++ related. It's sorta relevant.

    "Libraries like STL?" I've never heard a bunch of headers called a library before ... except, obviously, by Stepanov.

    What next? Re-implement libc.so.6? It's obviously in dire need of re-implementation. How hard could it be to do so in self-modifying MML assembler so that it copes with calls to libc.so.5, libc.so.4, etc ... and then just add a back-end to the assembly language of choice?

  • (cs) in reply to mxx
    mxx:
    If this is C or C++ (and I'm quite sure it is), comparing NaN does not throw exceptions, it simply returns false for any comparison; heck, C doesn't even know about exceptions.
    It has signals. Namely, SIGFPE. Which stands for (you guessed it) floating-point exception.
    A NaN is an encoding signifying Not-a-Number. A quiet NaN propagates through almost every arithmetic operation without raising an exception; a signaling NaN generally raises an exception when occurring as an arithmetic operand.16)
  • Capt. Obvious (unregistered) in reply to Iago
    Iago:
    Greg:
    Most often, !0 is defined as MAX_INT
    You may be thinking of Microsoft Visual Basic, which does indeed define True as 0xFFFF, but is not in fact a C compiler.
    Indeed, the whole Variant_Bool uses 0xFFFF(FFFF) as true. Drove me nuts, as implict casts (even in visual studio) have messed this up.

    I believe OS2 also used that schema for TRUE.

    I thought it was evil when I first saw it, but then came to realize it's beauty. It lets you use bitwise operators intermingled with binary values, and have it be correct for that bit.

    That said, in all my projects, !0 = 1, and 1 = false;

  • (cs) in reply to Mike Dimmick
    Mike Dimmick:
    !0 is non-zero. It is not necessarily 1.
    The only thing more annoying than being pedantic is being pedantic and wrong.
    The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int .
    Now, it doesn't have to necessarily materialize a 1 in register/memory if you're using if(!something) [it could simply do a branch if zero instruction], but it DOES if you're actually storing !something in a variable.
  • (cs) in reply to Duke of New York
    Duke of New York:
    Greg:
    Actually, although it depends on the compiler, usually

    !0 != 1

    Most often, !0 is defined as MAX_INT (or something similar), so for a 16 bit system:

    !0 == 0xFFFF

    Much better to use the compiler defined TRUE and FALSE, or define your own as #define FALSE 0, and #define TRUE !FALSE and let the compiler decide what ! means and do the same thing every time.

    No. Just no. Go read the C standard for the ! operator (and all of the relational operators), and sin no more.

    More specifically, Greg should go and look at the part about the bitwise-NOT operator (~), which is clearly what he's mistakenly thinking of in this case. Greg, ! is logical-NOT.

Leave a comment on “Code Ownership Gone Awry”

Log In or post as a guest

Replying to comment #:

« Return to Article