Live data from Hacker News

C Strings and my slow descent to madness

deusinmachina.net

41–50 of 329 posts

Re: C Strings and my slow descent to madness

#41
post #8

I've been wondering lately why many people write c in c++ rather than just c. I think this might be the reason.

For a long time on windows the official MS recommendations was to use the c++ compiler for c projects.

Which was exerbated by an obsolete c compiler that only supported c89.

Re: C Strings and my slow descent to madness

#42
post #17

C strings are bad for sure. Consider those raw assembly. Instead of using it directly get some decent string library ASAP and use it exclusively.

They are just arrays, like everything else in the language. If you don't want to manage plain arrays, better look for a different language.

You are free to make good use of strings as arrays. I've written tons of code including firmware for MCU so I think I'll keep to my own practices.

Re: C Strings and my slow descent to madness

#45

In well-written C, you don't work with strings the way you do in other HLLs. For example, extracting and copying substrings is something unnecessary, unless you want to modify the parent string. Otherwise, a substring is represented by a pointer and a size_t length, and can easily be printed that way via the "%.*s" printf specifier: const char *s = "Hello World!"; const char *world = s + 6; size_t world_len = 5; prin…

On other HLLs it is easy to have subviews on other strings. C makes is needlessly hard by requiring null termination in half the APIs.

Re: C Strings and my slow descent to madness

#46
post #3

It's unfortunate the author put the arrays-are-pointers thing so early in the doc, as that's a very beginner-to-C mixup and really nothing at all to do with strings. Otherwise, yep. It's pretty bad. C is a great language, but its string handling is definitely garbage. You get used to it pretty quick, and it's not hard to write a handful of sane wrappers or a simple string library for your own use, but the standard li…

I don't see any mention or insinuations of arrays-are-pointers anywhere in the article. Am I missing something?

Re: C Strings and my slow descent to madness

#47
post #6

Yes this is something to get use to. The BSDs created strlcpy(3) and wcslcpy(3) https://man.openbsd.org/strlcpy.3 https://man.openbsd.org/wcslcpy.3 which to me will help with some of these issues. Too bad other Operating Systems do not have these. On Linux there is libbsd to get these, but I would like to see these to be added to the stdc. Instead the c23 standard is messing with realloc(3) which could break some old…

strlcpy is nice due to the guaranteed NUL termination.

strlcpy is not so nice due to the strange (IMO) return value of the number of characters in the source string. Which could be the number of characters copied or much, much larger than the number of characters copied. snprintf does the same thing.

So using strlcpy is safe (by C's low bar) but using the return value may be highly unsafe.

Re: C Strings and my slow descent to madness

#48
`strlcpy` is the function you probably want. but again it is not standard. https://lwn.net/Articles/507319/

I think the reason people don't want to standardise this kind of function is it often gives wrong behaviour. for example if you are trying to copy a string into a fixed buffer and its too long then often it is an error or potentially even a security bug to truncate it. so these functions generally do the 'wrong' thing even though they are 'safer'. if you are dealing with static buffers then I think you should be explicitly checking the source fits in the target and then handling the error case. you could even have a function like `strlcpy` that does `strlen` then checks if it fits, then does the copy or return an error code. alternatively, if the string should always fit and you don't want to handle the error case then the safe thing to do is check at runtime that it fits then abort the program if it doesn't fit.

Re: C Strings and my slow descent to madness

#49
For initial string input, i.e. from a network/file/terminal stream, using fgetc and/or fgets plus code to verify and sanitize makes the most sense IMO.

This does mean you have to write a lot of C code for what would be simple tasks in other languages, e.g. a correct file open, read-to-dynamically-allocated-memory, and file close with good error checking is a full page (at least) of dense code in C and just two lines in Python.

If you've done a good job sanitizing and verifying all the input to your program, only then does it becomes relatively safe to use the standard string functions, with caveats for multithreading.

Asking ChatGPT to compare and contrast fgetc and fgets is a good place to start, and then ask how to use fgets to handle errors during stream I/O, and what can go wrong with multithreading etc. Then take a look at the sqlite source code for in-house C-string handling, here's the take-away comment:

"Because there is no consistency, we will define our own."

https://github.com/sqlite/sqlite/blob/master/src/util.c

Re: C Strings and my slow descent to madness

#50
post #33

> Our last function is strcmp. It looks at two strings and determines whether they are equal to each other or not. If they are it returns 0. If they aren’t it returns 1. No it doesn’t. RETURN VALUES The strcmp() and strncmp() functions return an integer greater than, equal to, or less than 0, according as the string s1 is greater than, equal to, or less than the string s2. The comparison is done using unsigned charac…

I've added a footnote to my incorrect explanation and credited you. I'm still a C noob so thank you for pointing this out!
Post reply on HN