Spot the WTF



  • So i was looking through some of my older code and i was agast at something I'd written in C:

    [code]
    /* Gets 8 bytes from the specified handle, then sprintf's them into the output array, creating a nice hex line.

    / char[] getNext8BytesfromFile(FILE theHandle) {

    byte[8] buff;

    fread(theHandle, &buff, sizeof(byte), 8); // if it overflows, we dont care. glibc will just return NULL for EOF.

    /* size of the buffer should be 7 + 16 + 1 + 8 (7 spaces + 2 chars for each byte, a space, then the chars from each one of the bytes, if printable. */

    byte[32] outbuf;

    int iCount =0; // internal counter.

    for(iCount =0;iCount<sizeof(buff);iCount++)

    {

    }

    }

    [/code]


    Now, time just doesnt wait for me. Later on in that exact same app was the following:


    [code]
    #IFDEF STATIC_LEN

    int max_ByteCount = 16; // this should remain constant.



    #ELIF

    int max_ByteCount;

    cmdscanf("-bc=%i", &max_ByteCount);

    if(!max_bytecount)

    { cmdscanf("-bc=0x%h", &max_ByteCount); if (!max_byeCount) { max_bytecount = 16; } }

    }

    #ENDIF

    [/code]


    No comments around it, only that one lone comment. I can only assume that it was looking for either a -bc=0x3F or -bc=34 on the command line somewhere, as cmdscanf was as follows:

    [code]

    bool cmdscanf(...) {

    int k;

    for(k=0;k<argc;k++)

    {

    if(sscanf(argv[k],...)) {return true; }

    }

    return false;



    }

    [/code]



    I have NO idea how my C compiler allowed this, but it somehow worked.



  • char[ ?



  • 'char' is a legit C type. Depending on your C library, its either 2 byte's or 1.



  • @indrora said:

    'char' is a legit C type. Depending on your C library, its either 2 byte's or 1.

     

    But char[ without a matching ] ?

     



  • @emurphy said:

    @indrora said:

    'char' is a legit C type. Depending on your C library, its either 2 byte's or 1.

     

    But char[ without a matching ] ?

     

    Community Server BBCode maps []] to a single []. Preview tab FTW.



  • Lessee... My C is nothing more than College level, but...

    • The function doesn't actually return jack, when it should return a char array.
    • the for loop inside the function does nothing but warm the room.
    • you set iCount twice, as if you started thinking about a while loop and then changed your mind.
    • you misspell max_ByteCount as 'max_bytecount' and 'max_byeCount'. While not all compilers may care about case, I'm fairly certain they mind about missing letters.
    • you take a variadic function to do nothing with the eventual args but sscanf them to oblivion? I don't really understand what you do with cmdscanf. Are argc and argv actually available there, or are they the ones from main? I'd guess you'd have to declare them somewhere...
    • gcc has many interesting things to say about the code snippet, starting with:
      • wtf.c:4: error: expected identifier or ‘(’ before ‘[’ token (corresponds to the line about char[ ] getNext8BytesfromFile(FILE* theHandle) {

  • Discourse touched me in a no-no place

    @indrora said:

    'char' is a legit C type. Depending on your C library, its either 2 byte's or 1.
    If your chars are anything other than one byte, you're not using C.



  • @PJH said:

    @indrora said:

    'char' is a legit C type. Depending on your C library, its either 2 byte's or 1.
    If your chars are anything other than one byte, you're not using C.


    More on that: sizeof(char) is guarunteed to be 1. However, that "byte" may or may not be an octet (8 bits).



  • @indrora said:

    <font size="2" face="Lucida Console"></font>

    <font size="2" face="Lucida Console">fread(theHandle, &buff, sizeof(byte), 8); // if it overflows, we dont care. glibc will just return NULL for EOF.</font>

    The arguments for this fread are totally off; my manpage says:

    size_t fread(void *ptr, size_t size, size_t nmemb, FILE stream);

     If this even did compile, you'd be reading (&buff) bytes of data from the stream (FILE)8 and writing them to *theHandle and beyond...

    Or the SDK you were using was horribly broken (I'm curious to know what it was).  Maybe that explains the remaining WTFs ;)



  • @Ronuk Raval said:

    @PJH said:

    @indrora said:

    'char' is a legit C type. Depending on your C library, its either 2 byte's or 1.
    If your chars are anything other than one byte, you're not using C.


    More on that: sizeof(char) is guarunteed to be 1. However, that "byte" may or may not be an octet (8 bits).

    If the sizeof(char) is guaranteed to be 1 in all C, then why is it recommended to always use sizeof(char) when allocating a char array?

    It's been a long time since I checked the C standards for this, but I seem to recall it is not actually required to be a byte - it's just that it normally1 is.  But, at a minimum, I'm fairly certain that it's legitimate for a non-ANSI C to have sizeof(char) == 2.

    However, that being said, it's this kind of nonsense which has stuck 'short' at 16 bits, 'int' and 'long' at 32 bits, and thus created a need for a 'long long' - and thus later on, a 'long long long'.

    1 And by 'normally', I mean so fricking often that the vast majority of us have never encountered an environment where it isn't - despite the fact that the existence of unicode certainly should be encouraging such environments.


  • Discourse touched me in a no-no place

    @tgape said:

    If the sizeof(char) is guaranteed to be 1 in all C, then why is it recommended to always use sizeof(char) when allocating a char array?
    Any reference material making this reccomendation is seriously mis-informed, and IMHO, untrustworthy. If it starts casting the return from malloc() or uses void main(), then doubly so. @tgape said:
    But, at a minimum, I'm fairly certain that it's legitimate for a non-ANSI C to have sizeof(char) == 2.

    Non-ANSI 'C' can do whatever the hell it likes, since it isn't C.

    You, perhaps, are thinking of multibyte characters which are mentioned in The Standards?

    @tgape said:

    However, that being said, it's this kind of nonsense which has stuck 'short' at 16 bits, 'int' and 'long' at 32 bits, and thus created a need for a 'long long' - and thus later on, a 'long long long'.
    Those are lower limits, not absolute limits.

    It's entirely possible for them to be longer.

    Anyway, back to char - it must always be one byte long, with the number of bits in a byte being at least 8 - from one of The Standards(Working Draft, 1997-11-21, WG14/N794 J11/97-158):

     

    3.5 Character
    A bit representation that fits in a byte. The representation of each member of the basic character set in both the source and execution environments shall fit in a byte.

    [...]

    5.2.4.2.1 Sizes of integer types <limits.h>
    1 The values given below shall be replaced by constant expressions suitable for use in
    #if preprocessing directives. [...]

    Their implementation-defined values shall be equal or greater in
    magnitude (absolute value) to those shown, with the same sign.
    — number of bits for smallest object that is not a bit-field (byte)
    CHAR_BIT 8



  • the REAL wtf is that a) there's no EOF checking (I assumed the compiler's library, glibc in this case, would force NULL to be returned when I passed EOF (which it does, but Borland's C lib and a few others dont) b) cmdscanf makes no assumptions about type or overflows. that is if int is defined as "int8" and -bc=0x3FF is passed, somethings getting clobbered. c) my fread was macro'd to look more like PHPs (thus breaking things horribly). Amazingly enough, I forced gcc to compile it with a few things (like the bracket matching). Some of you also noticed that there was no code in the for loop. I omitted the even more horrible code to write out buff to a string like so

    0xOFFSET 00 00 00 00 00 00 00 00 ........


  • Discourse touched me in a no-no place

    @indrora said:

    the REAL wtf is that a) there's no EOF checking (I assumed the compiler's library, glibc in this case, would force NULL to be returned when I passed EOF (which it does, but Borland's C lib and a few others dont)
    I'm assuming you've changed your behavior now?



  • @PJH said:

    @indrora said:
    the REAL wtf is that a) there's no EOF checking (I assumed the compiler's library, glibc in this case, would force NULL to be returned when I passed EOF (which it does, but Borland's C lib and a few others dont)
    Ah. There's nothing like documentation by experimentation, instead of actually reading it. If you had, you'd have found out that fread() tells you whether or not it succeeded, partially succeeded, or totally failed - you test for none of these, and instead rely on undocumented behaviour of a particular compiler which no other compiler is obliged to perform. On the other hand, all the other compilers are obliged to tell you via the return value what it actually did.

    @indrora said:
    b) cmdscanf makes no assumptions about type or overflows. that is if int is defined as "int8" and -bc=0x3FF is passed, somethings getting clobbered.
    Indeed. The underlying sscanf() does no type checking. Documentation, again, tells you it won't - that's your job before you call it. (Though some compilers will helpfully attempt to check for you at compile time, there is no requirement to check at runtime.)
    @indrora said:
    ) my fread was macro'd to look more like PHPs (thus breaking things horribly).

    Abusing macros to force one language to 'look' like another is not really what macros are for.There are WTF's here - just not the ones you appear to think there are.

    a) my C book (my FATHER, who's an old C guy, who does stuff in C all the time) said fread was generally a void.
    b) secsscanf takes a type for each one.
    c) Dur, raplphie!


  • Discourse touched me in a no-no place

    @indrora said:

    my C book (my FATHER, who's an old C guy, who does stuff in C all the time) said fread was generally a void
    It would appear that your C book was either outright wrong, seriously out of date, or your program was written before '88 - before ANSI got involved.



  • @PJH said:

    @indrora said:
    my C book (my FATHER, who's an old C guy, who does stuff in C all the time) said fread was generally a void
    It would appear that your C book was either outright wrong, seriously out of date, or your program was written before '88 - before ANSI got involved.

    Could be the [url=http://www.catb.org/jargon/html/B/bullschildt.html]Bullschildt[/url] (Yes, this is a joke. I know that book was published in the '90s)

    Aside: God knows that having done a lot of programming in a language is not a guarantee of excellency.



  • @Adriano said:

    Aside: God knows that having done a lot of programming in a language is not a guarantee of excellency.

    So 30+ years of doing embedded stuff makes you an idiot. but meh, I've gotten better books and are using better languages.



  • @indrora said:

    @Adriano said:
    Aside: God knows that having done a lot of programming in a language is not a guarantee of excellency.

    So 30+ years of doing embedded stuff makes you an idiot.

    Wow, you fail at reading comprehension and basic logic.  He's not saying experience makes you an idiot, he is saying experience is no indication of proficiency.



  • @morbiuswilters said:

    he is saying experience is no indication of proficiency.

    Almost, but I wouldn't call it experience (and I didn't). Experience, for me, conveys a positive connotation which simply banging on the keyboard and repeating the same luserish code year after year doesn't. I'd search for examples, but this is thedailywtf.com .



  • @Adriano said:

    I'd search for examples, but this is thedailywtf.com .
     

    The truth is all around us.


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.