Live data from Hacker News

C Strings and my slow descent to madness

deusinmachina.net

91–100 of 329 posts

Re: C Strings and my slow descent to madness

#91
post #78
post #77

Earlier quoted context omitted.

C++ doesn’t require you to commit to all of its features and/or paradigms. Using it as you see fit is valid. Just don’t advertise yourself as a C++ programmer to the job market, as it’s not what most people expect. There’s nothing wrong with “C with classes and strings” idea by itself, if that is your choice or a consciously sufficient level of competence.

It doesn't require you to commit to all of its features, that's certainly correct. But it does require you to commit to its principles ; if you're needlessly passing naked pointers around, you're really writing C code with a C++ compiler.

I don’t see how it requires you to commit to any principles, if you can avoid those you don’t need and still successfully compile. That’s called “suggests” or “allows”, not “requires”. Yes, some people are writing C code with classes and strings in C++. That’s why we call this mode “C with classes and strings”. I believe that you are attached to these principles (see their benefits), and that is fine. But not everybody likes full-on C++.

Re: C Strings and my slow descent to madness

#92

If you are using C and do some non-trivial work with strings you should either use a good library to handle strings or build your own. It is not that difficult in practice. The old C std lib is, in my opinion, outdated, obsolete and a very bad fit for complex string handling, especially on the memory management side. In my own framework, the string management module is using a dedicated memory allocator and a "high l…

> the C std lib is the weakest part of the C language and it should only be used as a fallback. I've been musing for a while now: what would it look like if we were to discard the C library and design a new one, leaving the language itself intact?

I think it could be very nice.

C is not perfect, there are some parts of the syntax that I strongly dislike, like casting or function pointers declaration...

But it is overall a good enough syntax, much simpler than C++.

Re: C Strings and my slow descent to madness

#93

If you are using C and do some non-trivial work with strings you should either use a good library to handle strings or build your own. It is not that difficult in practice. The old C std lib is, in my opinion, outdated, obsolete and a very bad fit for complex string handling, especially on the memory management side. In my own framework, the string management module is using a dedicated memory allocator and a "high l…

> especially on the memory management side. Libc string functions don't manage memory. They can be used no matter where your strings are stored. It is more of a choice between generality vs convenience in common cases.

A lot of them require the string to be null terminated rather than taking a length.

Re: C Strings and my slow descent to madness

#94

If you are using C and do some non-trivial work with strings you should either use a good library to handle strings or build your own. It is not that difficult in practice. The old C std lib is, in my opinion, outdated, obsolete and a very bad fit for complex string handling, especially on the memory management side. In my own framework, the string management module is using a dedicated memory allocator and a "high l…

> the C std lib is the weakest part of the C language and it should only be used as a fallback. I've been musing for a while now: what would it look like if we were to discard the C library and design a new one, leaving the language itself intact?

There are several libraries or projects where people have done exactly that.

You often end up with some kind of structure, or variations of structures, for strings:

    struct string {
      size_t length;
      char data[];
    };

    struct string {
      size_t length;
      size_t alloc;
      char *data;
    };
Those are just examples. The tricky part is figuring out the different ownership use cases you want to solve. Because C gives you so much freedom and very little in the standard library, you end up with a lot of variations. You might use reference-counted strings, owned buffers, or string slices, etc. You might want certain types to be distinguished at compile-time and other types to be distinguished at run-time.

An example can be found in the Git source code.

https://github.com/git/git/blob/master/strbuf.h

The history of changes to this file is interesting as well. This is a relatively nice general-purpose string type—you can easily append to it or truncate it.

Re: C Strings and my slow descent to madness

#95

If you are using C and do some non-trivial work with strings you should either use a good library to handle strings or build your own. It is not that difficult in practice. The old C std lib is, in my opinion, outdated, obsolete and a very bad fit for complex string handling, especially on the memory management side. In my own framework, the string management module is using a dedicated memory allocator and a "high l…

> the C std lib is the weakest part of the C language and it should only be used as a fallback. I've been musing for a while now: what would it look like if we were to discard the C library and design a new one, leaving the language itself intact?

You can backport Rust standard library to C using https://github.com/eqrion/cbindgen .

Re: C Strings and my slow descent to madness

#96

If you are using C and do some non-trivial work with strings you should either use a good library to handle strings or build your own. It is not that difficult in practice. The old C std lib is, in my opinion, outdated, obsolete and a very bad fit for complex string handling, especially on the memory management side. In my own framework, the string management module is using a dedicated memory allocator and a "high l…

> especially on the memory management side. Libc string functions don't manage memory. They can be used no matter where your strings are stored. It is more of a choice between generality vs convenience in common cases.

I think this is the main culprit of the libc string functions, you have to provide buffers to store results, and the responsibility of managing those individually can be annoying, and bug prone, resulting in vulnerabilities.

Passing an allocator (like Zig) or a container (like in my framework) to anything that needs to allocate some memory to store a result is both explicit, low overhead and quite convenient in practice.

Re: C Strings and my slow descent to madness

#97

Earlier quoted context omitted.

> the C std lib is the weakest part of the C language and it should only be used as a fallback. I've been musing for a while now: what would it look like if we were to discard the C library and design a new one, leaving the language itself intact?

There are several libraries or projects where people have done exactly that. You often end up with some kind of structure, or variations of structures, for strings: struct string { size_t length; char data[]; }; struct string { size_t length; size_t alloc; char *data; }; Those are just examples. The tricky part is figuring out the different ownership use cases you want to solve. Because C gives you so much freedom an…

IMHO that does not solve the main problem, that is individual lifetime management.

I've seen many libs using this style of strings, not convinced by the practicality.

Re: C Strings and my slow descent to madness

#98

Earlier quoted context omitted.

> the C std lib is the weakest part of the C language and it should only be used as a fallback. I've been musing for a while now: what would it look like if we were to discard the C library and design a new one, leaving the language itself intact?

I think it could be very nice. C is not perfect, there are some parts of the syntax that I strongly dislike, like casting or function pointers declaration... But it is overall a good enough syntax, much simpler than C++.

Amending the syntax is fun but rapidly becomes a slippery slope; soon enough you find yourself designing a new successor language, as has been done many times before. Simply scrapping the mostly-unhelpful C stdlib and inventing new, modern abstractions for allocation, IO, text, threading, etc seems like a more tractable problem.

Re: C Strings and my slow descent to madness

#99
post #35

Earlier quoted context omitted.

>>I’ve also been having a blast with C because writing C feels like being a god Not trying to be a troll but as someone who has also written a lot of C in the past why do you feel like this?

It’s the access and control that it gives me! As when I’d pick Go because I was doing some concurrency, I can now explore a bunch of concurrency libraries, including some implementations that look a lot like Go channels. Want to watch a file for changes? I can do that all the way from taking to the kernel to picking a multi-platform library. I guess, I haven’t really found anything that I can’t do in C, and if I’m la…

Sorry to be "that person", but have you tried Rust yet? It checks a lot of your boxes:

- Access and control, nothing "behind your back"

- Low or high level, as you prefer

- Swap in different implementations (custom allocator, different async runtime, etc)

- Really powerful macros

- Strong conventions, safe by default (but you can break them, go into the weeds if needed)

Downsides compared to your list:

- More complex than C or Go (though less than C++)

- Only one production compiler, and everyone assumes `cargo` build system (though both are very good)

- Library ecosystem not quite as extensive (though there is a lot of good stuff on crates.io, and you can always write bindings to C)

The little things that seal the deal:

- Enums (tagged unions without the danger or boilerplate)

- Zero-cost closures

- Incremental compilation

- "If it compiles, it probably works"

- Standardized documentation via `rustdoc`

- Module system

Re: C Strings and my slow descent to madness

#100

Okay, I agree that by default , C strings are bad. But it doesn't have to stay that way. Someone else in the comments mentioned antirez's sds library for dynamic strings. This works, but you could also easily roll your own. All you need is an init function, and perhaps an assert or other check at the end of it that the string has a nul terminator. At that point, type checking will let you blindly pass those strings (…

> by default , C strings are bad. C strings aren't bad. They can't be, because they don't exist. C doesn't have strings. And that is the issue. As you say, things get a lot better when you actually introduce strings as a concrete concept rather than a set of lose conventions.

I don't think it's useful to pretend C doesn't have strings when it has string literals.

WUFFS doesn't have strings. That's what a language which doesn't have strings looks like, you can't write "Hello, world" in WUFFS because it involves Strings, which WUFFS doesn't have, and I/O, which WUFFS also doesn't have.

A pretence that C doesn't have strings because it lacks a concrete string type in the language itself also seems like you'd be claiming C++ doesn't have strings, Zig doesn't have strings, and Rust came pretty close to not having strings (for a while it was mooted to make Rust's str just a slice [u8] but today Rust does bless str as a distinct type even though e.g. &str and &[u8] aren't very different)

Post reply on HN