News for hackers. Stuff that matters.
Re:Show HN by Someone on Saturday December 03, 2022 @11:37AM (#33844717)
The problem is that C doesn’t have strings; it has functions that treat sequences of non-zero bytes followed by a zero bytes as if they are strings.

So, you can’t ask it to create a string that contains the result of appending a string to another one. If you want to append two ‘strings’, you have to create a buffer large enough to hold the result, and then copy in the two sequences of bytes. And even for doing that, the library functions aren’t optimal. The basic “append this string’s data to that string, assuming there’s enough space to do so” function is strcat. It walks the first string to find the zero byte, but to “create a buffer large enough to hold the result” you already must do that.

See for example https://stackoverflow.com/questions/21880730/c-what-is-the-b...

Re:Show HN by jstimpfle on Saturday December 03, 2022 @11:52AM (#33844860)
You can use snprintf to easily achieve any concatentation you'd like.

    len = snprintf(buffer, buffersize, "%s%s%d", string_1, string_2, int_1);

    if (len + 1 /*NUL*/ > buffersize)
    {
        // not enough space
    }
You can also use this to dynamically allocate any formatted string

    len = snprintf(NULL, 0, ....);

    buffersize = len + 1;  /* NUL */
    
    buffer = allocate(buffersize);

    snprintf(buffer, buffersize, ... /*same args as before*/);
Re:Show HN by tom_ on Saturday December 03, 2022 @01:47PM (#33846122)
I like the printf family too. Any time you're doing a bunch of strcat or whatever it's almost always massively easier to use a format string to get the same result. Very easy to get the desired width/precision/alignment, and if you need numbers, printf has your back. It even does the bounds checking for you! (And how often do you get that in C.)

It won't be as fast, but it's almost always not a problem, and the nice thing about C and C++ is that the char-by-char route is still available when it is.

I like to use asprintf, when available: https://man7.org/linux/man-pages/man3/asprintf.3.html - and when not available, I add it, along the lines of the snippet you present.

Here's something I've found a useful upgrade to asprintf, as it frees the passed-in buffer after expanding the format string. You can just pass the same char ** repeatedly and it'll update the char * appropriately each time.

    int xasprintf(char**p,const char *fmt,..) {
        int n=0;
        char *p2=nullptr;
        if(fmt) {
            va_list v;
            va_start(v);
            n=asprintf(&p2,fmt,v);
            va_end(v);
        }
        if(n>=0) {
            free(*p);
            *p=p2;
        }
        return n;
    }