• Maia Everett (github)

    TRWTF is chaining strcat calls, which is Schlemiel the Painter's algorithm. (The underlying issue, of course, is that strcat is horribly designed.)

    https://www.joelonsoftware.com/2001/12/11/back-to-basics/

  • Tim (unregistered)

    But how does it know how long each of the 4096 records are?

  • Sauron (unregistered)

    Out of curiosity, are there even valid use cases for proprietary file systems? (Like, are there some embedded OSes that have hardware constraints so strict that they require something custom?)

  • (nodebb)

    But this code is so much more maintainable than having it all in a single string literal. What would happen if you need to change the number of records? With this code, you just have to change one simple value. If it were all in one string, you'd need to hunt through a huge string literal to find the value you need to change.

  • (nodebb) in reply to Sauron

    Out of curiosity, are there even valid use cases for proprietary file systems?

    Aren't most file systems proprietary? NTFS has been mostly reverse engineered, but I think it's still proprietary.

  • (nodebb) in reply to Jaime

    Aren't most file systems proprietary? NTFS has been mostly reverse engineered, but I think it's still proprietary.

    "Proprietary" is probably the wrong word in context. I think that "domain-specific" might be better.

  • (nodebb) in reply to Maia Everett

    I wouldn't say that strcat is horribly designed. It's appropriately designed for C strings. C strings, on the other hand, are horribly designed... In a way, the design is elegant in its simplicity, but it's definitely not performance oriented.

  • (nodebb) in reply to tom103

    C strings were designed when memory optimization was a priority. You only need to waste one byte for the null terminator, not multiple bytes for a length prefix, or even worse, a dope vector with a length and pointer.

  • Dan S (unregistered) in reply to Tim

    to clarify: it's not 4096 records, but a file with fixed size records of 4096.

  • (nodebb) in reply to Maia Everett

    While I realize it's easy to avoid, the performance problems of Schlemiel the Painter are probably overblown unless you're dealing with very long strings and hundreds of concatenations. I usually use sprintf(), not just for performance but because it's clearer, but for short strings it's possible that the overhead of parsing the format string is worse than the back-and-forth of Schlemiel (unless the compiler is able to optimize it all away).

  • Sou Eu (unregistered) in reply to Dan S

    Dan, to be more pedantic, the 512 is block size, not necessarily record size.

  • Splatmandeux (unregistered)

    There were some APIs (not necessarily sure how the underlying filesystem was implemented) on old IBM or VAX mainframes (my C language class used an ancient VMS system) where you had to specify if a file consisted of fixed size records vs byte stream, random access vs sequential, etc. I guess filesystems would enforce that in some way back then.

    I kind of think the same 'statement of intent' API could be useful today as it would provide hints to the OS about read-ahead, caching policy, etc.

  • Argle (unregistered)

    I taught C programming during the 80s and early 90s. I was stunned to see how many C programmers thought you had to supply the NUL yourself. And I'm not talking about my students. That blunder was quickly pointed out when I returned assignments. No, this was so often in "professional" code. sigh Forty+ years of this and still trying to keep my chin up.

  • (nodebb) in reply to Barry Margolin

    OK. Here's my alternate extended Pascal string implementation:

    The first byte is the length of the string. If the length is less than 128, the next byte is the first byte of text. Thus, any string from 0 to 127 characters is the same length as its C equivalent.

    If the top bit of the first byte is set, then the next byte is the high byte of the length and the text starts at byte 3. Note that this means that in strings of length 128 to 255, the second byte is zero.

    You can repeat the semantics with the second byte and subsequent bytes if you want strings that are more than 65535 characters long.

    Even for short strings, this incurs an extra comparison and a jump (to avoid loading the second byte) to get the length, compared to a Pascal string, but it's still faster than counting the characters.

  • Duke of New York (unregistered)

    Joel had made many critiques of the form "a clueless programmer could misuse it." That is not entirely meritless, but neither is it unequivocally a problem with the technology.

  • Dan S (unregistered) in reply to Sou Eu

    Nope. This is a proprietary filesystem. One of the file types is fixed-N, where N is the size of records.

  • (nodebb)

    Record size of 4096. But what's the block size? Having flashbacks to JCL.....

  • Dan S (unregistered) in reply to sdh

    The HW block size is irrelevant. This is what a user application is passing to fopen().

  • Duston (unregistered)

    "Having flashbacks to JCL....." JTSD should be in the DSM.

  • bill99 (unregistered) in reply to jeremypnet

    Hmm. I think there are actually 2 numbers you need to record for a string variable - how long the string is, and the maximum length it can be.

  • ismo (unregistered) in reply to jeremypnet

    And then your code breaks when somebody uses UTF-8 strings . Or in many european lanuages chars like åäöÅÄÖ :-)

  • MaxiTB (unregistered)

    strcpy(str, "Now you see me"); strcat("\0Now you don't");

  • (nodebb) in reply to MaxiTB

    strcat("\0Now you don't");

    You missed something :)

  • (nodebb) in reply to R3D3

    Yeah, typed it on my phone - it's the worst way to code lol

  • (nodebb) in reply to MaxiTB

    Yeah, typed it on my phone - it's the worst way to code lol

    No, it's not.

Leave a comment on “Terminated Nulls”

Log In or post as a guest

Replying to comment #:

« Return to Article