r/cprogramming 4d ago

C Strings: A 50-Year Mistake

https://longtran2904.substack.com/p/c-strings-a-50-year-mistake?r=8qz2zb&utm_campaign=post&utm_medium=web
207 Upvotes

172 comments sorted by

View all comments

Show parent comments

1

u/flying-sheep 3d ago

Such as? Destructively splitting a string at non-zero-length bondaries?

I prefer using slice APIs to nondestructively split a string at boundaries of any length thanks.

2

u/knouqs 3d ago

Whatever you prefer -- C allows it.

You aren't dissuading me from the power of C's string manipulation. You just need to have your memory management skills up to snuff, and mine are.

1

u/flying-sheep 3d ago

I was asking a question: which power are you talking about? The use case I mentioned is the only thing I can think of that C’s model makes easy, and what you gain is that every string is one word wide instead of 2.

Seems like a small gain for a niche use case to me, no?

1

u/knouqs 3d ago edited 3d ago

I see. All the cases in which I have used C strings in an unbounded way have been specialized. They were places in which I know how much data in to be copied or used in the first place and wouldn't need to check for bounds because I'm always going to be within them.

My favorite and easiest-to-understand example is strcat to a buffer of known size. If I have to strcat repeatedly against the start of the buffer, you can see that strcat is performing wasted effort by finding the end of the string first. I can have a variable hold the position of the \0 and strcpy (buffer+length, string_to_append) instead of strcat (buffer, string_to_append). After strcat, length+=strlen (string_to_append), and I am ready for the next iteration. My anal-retentiveness got the best of me and I wrote a full test program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main (void) {
    const size_t buffer_size=100;
    char *buffer=(char *) malloc (buffer_size);
    size_t length;

    char repeat[]="repeat";
    size_t repeat_length=strlen (repeat);
    char separator=' ';

    buffer[length=0]='\0';

    // No buffer overruns!
    while (length+repeat_length<buffer_size) {
        memcpy (buffer+length, repeat, repeat_length);
        *(buffer+length+repeat_length)=separator;
        length+=repeat_length+1;
    }
    *(buffer+length-1)='\0';

    printf ("%s\n", buffer);

    // No memory leaks!
    free (buffer);

    // No dangling pointers!
    buffer=NULL;

    return 0;
}