News for hackers. Stuff that matters.
Re:Best aspects of C by adwn on Tuesday November 17, 2020 @10:43AM (#25125034)
> There is little of needless code in standard library. And what there is, believe me, over the decades was really polished.

Wrong. Counter-example: locales [1]

Also: String handling, which is responsible for so, so, so many security vulnerabilities. The underlying cause is zero-terminated strings (instead of using start/end pairs or start/length pairs). You can't even tokenize a string without either copying or modifying it!

Also also: just a single, apologetic mention of undefined behavior. Responsible – in cooperation with over-zealous compiler writers – for so many more bugs not already caused by improper string handling.

[1] https://github.com/mpv-player/mpv/commit/1e70e82baa9193f6f02...

Re:Best aspects of C by flohofwoe on Tuesday November 17, 2020 @11:11AM (#25125407)
I love C but I think most of the C standard library is useless and outdated rubbish (pretty much everything above the mem...() and math functions). The entire IO and memory-management areas should have been either thrown out of the standard library, or updated 20 years ago to keep up with low-level operating system features.

But one of the best features of C is that you can mostly ignore the standard library and still enjoy "C the language", e.g. nobody ever choose C for its standard library ;)

(also re UB etc...: use the mighty trio UBSAN, ASAN and TSAN!)

Re:Best aspects of C by bhaak on Tuesday November 17, 2020 @02:01PM (#25128083)
What do you use then if you don't use the standard library?

What is the standard library for the C which ends all the other standards libs?

Re:Best aspects of C by flohofwoe on Tuesday November 17, 2020 @03:02PM (#25128933)
For IO, memory management and similar "low-level services" it's often fine to call the underlying operating system functions directly and with this also make use of more powerful features than the standard library can provide, such as async IO, virtual memory etc (or wrap those OS calls into your own cross-platform wrapper functions). There's also plenty of libraries which do this for you, like libuv (but integrating such big libs is often not trivial).

Same for string handling/processing, there are specialized libraries out there which do a specific job better than the rather generic standard library functions (this is also true for the C++ stdlib), one just has to find those libraries.

PS: I don't think that a "batteries included" standard library (like python has) would even make sense for C, such a library would need to be opinionated by definition, better to keep (too many) opinions out of the standard, as this road just leads to another C++ ;)

Re:Best aspects of C by arcticbull on Tuesday November 17, 2020 @04:09PM (#25129868)
C++ is IMO defined by a complete lack of opinion. They just standardized every opinion. For everything. C++ would be a much better language if it showed some opinion, even if I disagreed with it.
Re:Best aspects of C by anfilt on Wednesday November 18, 2020 @04:38AM (#25134873)
That's honestly how I also feel about C++ in when I look at how often they are adding new things.
Re:Best aspects of C by WalterBright on Tuesday November 17, 2020 @10:44PM (#25132964)
In my long C career, I invented string library after string library. They all turned out to be garbage. The common cause of their failures is their inability to interact with any other C code.
Re:Best aspects of C by flohofwoe on Wednesday November 18, 2020 @04:56AM (#25134984)
Agreed, but that's an issue for all "interface types" on API boundaries (another similar issue is vector and matrix types in math libraries). IMHO a C string library must still be able to efficiently consume and produce vanilla zero-terminated "const char*" string data (and at a stable address, unlike for instance std::string) even if they mostly work with {pointer,length} ranges internally.
Re:Best aspects of C by WalterBright on Wednesday November 18, 2020 @07:06AM (#25135868)
C strings are so ubiquitous that the ABI impedance mismatch is just too annoying.
Re:Best aspects of C by asveikau on Tuesday November 17, 2020 @04:54PM (#25130441)
> Same for string handling/processing, there are specialized libraries out there which do a specific job better

I actually can't think of a lot of these that are super common across projects.

ICU is probably the most notable one, with its particular focus on unicode correctness.

A lot of large projects end up writing their own string library of sorts.

Re:Best aspects of C by bigbubba on Tuesday November 17, 2020 @06:10PM (#25131153)
There's bstr, I've come across that a few times.
Re:Best aspects of C by einpoklum on Tuesday November 17, 2020 @03:09PM (#25129048)
You can use something like GitHub or Conan to find specific useful C libraries.

There isn't a universally recognized "standard library replacement" (and people argue about what parts of the standard library they don't like), but here:

https://stackoverflow.com/questions/486383/safer-alternative...

are a few options:

* Glib (the basis for Gtk): https://developer.gnome.org/glib/stable/glib.html

* The Apache Portable Runtime (APR): http://apr.apache.org/

Caveat: I haven't used them.

Re:Best aspects of C by 1vuio0pswjnm7 on Tuesday November 17, 2020 @06:26PM (#25131271)
djb's libraries (answer to first question)
Re:Best aspects of C by adrift on Tuesday November 17, 2020 @02:12PM (#25128230)
Your own.
Re:Best aspects of C by lmm on Tuesday November 17, 2020 @10:19PM (#25132821)
> But one of the best features of C is that you can mostly ignore the standard library and still enjoy "C the language", e.g. nobody ever choose C for its standard library ;)

C is one of the hardest languages to do this with given its anaemic dependency management.

> (also re UB etc...: use the mighty trio UBSAN, ASAN and TSAN!)

All of which will miss some cases, even in combination.

Re:Best aspects of C by pornel on Tuesday November 17, 2020 @11:20AM (#25125540)
There's a lot of subtly broken stuff in C stdlib. For example, time.h calls that may touch the TZ env var aren't thread-safe, because getenv is unsafe (it gives a pointer to its internal globally mutable data structure without locks).

Because C is so bare-bones, it usually leans on POSIX as its extended standard library, and that is also full of old cruft.

Re:Best aspects of C by einpoklum on Tuesday November 17, 2020 @03:12PM (#25129100)
One thing that is not-so-subtly broken is re-entrancy (e.g. in functions like `strtok()`; fixed later with `strtok_s()` in C11:

https://en.cppreference.com/w/c/string/byte/strtok

About getenv: This sort-of fixed with `getenv_s()` in C11

https://en.cppreference.com/w/c/program/getenv

Re:Best aspects of C by loeg on Tuesday November 17, 2020 @03:17PM (#25129184)
Re: getenv_s: Annex K is (still) optional. Compliant C11+ implementations may not have getenv_s.
Re:Best aspects of C by josephcsible on Tuesday November 17, 2020 @05:39PM (#25130875)
This is an understatement. The only relevant platform that supports Annex K is MSVC, and this is unlikely to change any time soon.
Re:Best aspects of C by loeg on Tuesday November 17, 2020 @07:39PM (#25131791)
And even MSVC does not actually implement the API specified in Annex K. Annex K was inspired by MSVC's design, but they diverged:

> Microsoft Visual Studio implements an early version of the APIs. However, the implementation is incomplete and conforms neither to C11 nor to the original TR 24731-1. For example, it doesn't provide the set_constraint_handler_s function but instead defines a _invalid_parameter_handler _set_invalid_parameter_handler(_invalid_parameter_handler) function with similar behavior but a slightly different and incompatible signature. It also doesn't define the abort_handler_s and ignore_handler_s functions, the memset_s function (which isn't part of the TR), or the RSIZE_MAX macro.The Microsoft implementation also doesn't treat overlapping source and destination sequences as runtime-constraint violations and instead has undefined behavior in such cases.

[0]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm

Re:Best aspects of C by icedchai on Wednesday November 18, 2020 @10:38PM (#25145959)
This makes sense when you consider the history of C. Multi-threading was a relatively late add on, and outside of the standard library.

When I learned C (early 90's), multi-threading wasn't even something you considered. It was either multiple processes or an event loop with select/poll.

Re:Best aspects of C by kevin_thibedeau on Tuesday November 17, 2020 @03:49PM (#25129620)
strtok_r() is everywhere and easy to retrofit. It's also easy to implement using strspn() and strcspn() if you don't have it.
Re:Best aspects of C by Cloudef on Tuesday November 17, 2020 @10:50AM (#25125124)
Locale handling and most of the str* function in libc indeed are quite bad. The only sane function for "C strings" is snprintf.
Re:Best aspects of C by kazinator on Tuesday November 17, 2020 @11:44AM (#25125859)
Ones like strspn, strcspn, strpbrk, strchr are also sane.
Re:Best aspects of C by asveikau on Tuesday November 17, 2020 @12:09PM (#25126238)
Except when you consider what a char is. Those don't handle multi-byte sequences.
Re:Best aspects of C by kazinator on Tuesday November 17, 2020 @12:53PM (#25126971)
Yes they do. What they don't do is search for multi-byte characters. You would not use them for that; you use them to look for ASCII delimiters. You can tokenize a UTF-8 string on ASCII delimiters using functions that are oblivious to UTF-8, and this is in fact a preferred technique in many programs.
Re:Best aspects of C by asveikau on Tuesday November 17, 2020 @01:25PM (#25127509)
I think I was going for more like: strpbrk and friends can't use a multi-byte sequence as a delimiter. And if a delimiter appears as part of a multi byte sequence, you may see strange results.

In a localized world searching for delimiters also starts to make less sense. Eg. I have been told it doesn't make sense to break on whitespace for Chinese text.

To be clear, I am not saying these functions are bad or evil or to blame for their limitations (a bunch of the problem space wasn't invented yet when they were introduced), just noting they have limits. A bunch of more recent languages and libraries have the same or similar issues, too.

Re:Best aspects of C by kazinator on Tuesday November 17, 2020 @08:58PM (#25132316)
strstr can find a multi-byte character in a multi-byte sequence. There is no ISO C function to find the first occurrence of any one of a bag of multi-byte characters, though it's not difficult to write one.

> I have been told it doesn't make sense to break on whitespace for Chinese text.

It could make sense to break on whitespace in some programming language or data format that allows Chinese (and other) identifiers.

A command interpreter that allows Chinese arguments (such as file names) wants to break on spaces, as usual.

> if a delimiter appears as part of a multi byte sequence, you may see strange results.

UTF-8 was designed by a dyed-in-the-wool C-and-Unix engineer, who ensured that such a thing can't happen. No character in the 0x00-0x7F range can occur in a multi-byte character.

The byte which starts a UTF-8 character cannot occur anywhere other than at the start, which is why we can use strstr to look for it.

Re:Best aspects of C by jesuscyborg on Tuesday November 17, 2020 @02:52PM (#25128767)
Use wcspbrk.

UTF-8 continuation characters are limited to the range \200 through \300 so there's basically zero chance that if you choose something like comma as your delimiter that it's going to tokenize the middle of a multibyte sequence.

Also take into consideration that, under the hood, functions like strpbrk() are typically accelerated by CPU instructions such as PCMPISTRI which doesn't support UTF-8 natively but it does support UCS-2.

Re:Best aspects of C by loeg on Tuesday November 17, 2020 @03:20PM (#25129224)
> so there's basically zero chance that if you choose something like comma as your delimiter that it's going to tokenize the middle of a multibyte sequence.

Not just "basically;" there is no possible collision between ASCII characters and any valid multibyte encoding. This can be seen somewhat visually in this table[1] and is an intentional aspect of the UTF-8 design.

[1]: https://en.wikipedia.org/wiki/UTF-8#Encoding

Re:Best aspects of C by asveikau on Tuesday November 17, 2020 @04:09PM (#25129879)
How about with joiners and combining characters? Eg. If you encode é as U+0065, U+0301 (\x65\xcc\x81), then search for 'e' and act on the result somehow, you fail to consider the whole glyph.
Re:Best aspects of C by loeg on Tuesday November 17, 2020 @04:43PM (#25130308)
Sure. You're talking about glyphs that are composed of multiple unicode codepoints; my earlier comment is true of single codepoints only. The comment I was responding to is also talking only about single codepoints (wcspbrk cannot represent delimiters longer than a single codepoint).

On joiners / combining characters: I'd encourage using composed normalization (NFC) rather than decomposed normalization (NFD).

Just curiosity: are there any glyphs that lack a single codepoint representation, where one of the joined codepoints is an ASCII character? (That only helps after normalization, of course.)

Re:Best aspects of C by jesuscyborg on Tuesday November 17, 2020 @05:15PM (#25130651)
Yes. ASCII uses \b as the combining character mark which is a convention that's always been widely supported by typesetting programs such as less and nroff. For example, A\b_ is A̲, and you can do the same thing with apostrophe and tilde for accent marks. There's also UNICODE emojis where two codepoints in sequence get joined together as a single glyph. Never underestimate the creative ways text can be used, or that standards just codify a long history of practices.
Re:Best aspects of C by loeg on Tuesday November 17, 2020 @07:37PM (#25131772)
Er, I was asking about unicode joining, not this roff \b thing. Sorry for the confusion. I'm aware that multiple-codepoint unicode glyphs exist; I'm asking if any of those involve a codepoint in the ASCII (1-127) range which cannot be normalized to a single codepoint (e.g., e + ' normalizes to a single codepoint é).
Re:Best aspects of C by jesuscyborg on Tuesday November 17, 2020 @08:08PM (#25132015)
Of course. Take for example mͫ (m+m) there's no way to represent that as a single codepoint. Combining marks can also be overlaid multiple times, e.g. m͚ͫ (m+m+∞) so the number of glyphs you can create is limitless. There's only a tiny number of the combinations that are possible which have a tinier normalized form. The new UNICODE combining marks work by almost exactly the same principles as the \b ASCII combining mark. That's why I mentioned it earlier.
Re:Best aspects of C by loeg on Tuesday November 17, 2020 @08:43PM (#25132227)
Thanks!
Re:Best aspects of C by kazinator on Tuesday November 17, 2020 @09:04PM (#25132345)
In what data format or programming language is 'e' a delimiter? One situation is floating-point constants, where 'e' is a delimiter indicating the exponent. However, if an é occurs in the middle of such a constant, whether as a single code point or a combined character, that is an error. The 'e' must be followed by an optional sign and one or more decimal digits.

The ISO C library string handling stuff is for systems programming, not for scanners and parsers for natural written language.

Re:Best aspects of C by Cloudef on Tuesday November 17, 2020 @11:57AM (#25126057)
True. With the snprintf comment I was mostly pointing out str* functions that are designed to either modify or concatenate strings.
Re:Best aspects of C by ringshall on Tuesday November 17, 2020 @08:35PM (#25132177)
It's been a long time since I've used C, but I recall strncpy being safe. I assume from context that I'm wrong, though.
Re:Best aspects of C by WalterBright on Tuesday November 17, 2020 @10:47PM (#25132981)
Every time I review code and see strncpy, I look closer because it's always used incorrectly. It's always about the terminating 0. Is the 0 there or not? Is the 0 part of n or not? Does the destination have to be n+1 in size for the 0?

I quit using it myself because I could never remember just what the exact protocol was for 0.

Re:Best aspects of C by Gibbon1 on Wednesday November 18, 2020 @03:37AM (#25134434)
Yeah used naively strncpy leaves you an unterminated string. Also like all of them it's up to the caller to predetermine if they will fail if called. So instead of having the checks in one place inside the string function. You have them scattered all over the code if at all.
Re:Best aspects of C by WalterBright on Wednesday November 18, 2020 @07:09AM (#25135886)
The irony of strncpy is it's supposed to eliminate memory corruption errors, but instead is a prolific source of them.
Re:Best aspects of C by Gibbon1 on Wednesday November 18, 2020 @11:52PM (#25146354)
I think I read somewhere the provenience of strncpy was to copy strings into a fixed length field which is why it has the deranged behavior of not terminating the string. Think file systems where the max file name is 8 characters. Or compilers that truncated variable names at 31.
Re:Best aspects of C by johntb86 on Tuesday November 17, 2020 @10:48PM (#25132986)
Strncpy doesn't add a \0 if it truncates the string, so the user has to remember to do that.
Re:Best aspects of C by Cloudef on Tuesday November 17, 2020 @11:37PM (#25133266)
strncpy is one of the trap functions. It's better avoided. Write your own or use snprintf.
Re:Best aspects of C by jjgreen on Tuesday November 17, 2020 @11:05AM (#25125333)
That [1] is a top-quality rant, but I fear for the author's blood-pressure
Re:Best aspects of C by donquichotte on Tuesday November 17, 2020 @11:21AM (#25125542)
Exhibit B: yes, the command that repeatedly prints `y` to stdout. Exhibit C: all handling of time, with time_t, struct timespec, timeval etc. We should just have a 64 bit uint representing nanoseconds from epoch, which would give us 585 years and get rid of much nonsense.

[1] https://github.com/coreutils/coreutils/blob/master/src/yes.c

Re:Best aspects of C by wool_gather on Tuesday November 17, 2020 @11:46AM (#25125885)
...? `yes` is not part of the C standard library.
Re:Best aspects of C by bigbubba on Tuesday November 17, 2020 @06:28PM (#25131290)
I think they meant to draw attention to the implementation of `yes` to showcase crustiness the C stdlib imposes on even a trivial program.

But of course GNU is kind of notorious in this regard. Compare their `yes` to OpenBSD's. It's night and day.

https://github.com/openbsd/src/blob/master/usr.bin/yes/yes.c

Re:Best aspects of C by identity0 on Tuesday November 17, 2020 @06:56PM (#25131510)
It's not that GNU is incompetent or overly bureaucratic or anything. It's that they really didn't want to infringe on Unix, and they presumed that Unix's yes would have been implemented in the most obvious, dead-simple way. And, as a plus, GNU yes can stream y's at like 10 GB/s, if you need that.
Re:Best aspects of C by throwhypothetic on Tuesday November 17, 2020 @11:24AM (#25125590)
Time should be a signed int with enough bits to go backward from the epoch at t=0 to the big bang at t=negative whatever.
Re:Best aspects of C by aw1621107 on Tuesday November 17, 2020 @11:47AM (#25125899)
> enough bits to go backward from the epoch at t=0 to the big bang at t=negative whatever.

For reference, the universe is about 13.787 billion years old [0]. That's about 13.787 * 10^9 * 365 * 24 * 3600 = 4.348 * 10^17 seconds, which (I think?) is a 59-bit number [1]. 10ths of a second will require 62 bits, which is right about at the edge of what a 64-bit signed integer will allow.

If you want milliseconds, you'll need at least 69 bits. For nanoseconds, you'll need at least 89 bits.

So you'll either need an integer type that's wider than what's natively supported in most hardware (thus potentially sacrificing performance), or you'll have to sacrifice precision.

[0]: https://en.wikipedia.org/wiki/Age_of_the_universe

[1]: https://www.wolframalpha.com/input/?i=13.787+*+10%5E9+*+365+...

Re:Best aspects of C by syrrim on Tuesday November 17, 2020 @03:54PM (#25129694)
struct timespec already exists and stores time as two 64 bit integers. Should last a little while.
Re:Best aspects of C by aw1621107 on Tuesday November 17, 2020 @08:31PM (#25132149)
Ah, that's something I wasn't aware of. Yeah, that scheme could work if you didn't need a single integer to represent time.
Re:Best aspects of C by AnimalMuppet on Tuesday November 17, 2020 @12:01PM (#25126116)
Just go for it. In the larger scheme of things, it's not that long until 128-bit CPUs.

I'm mostly kidding. But if you're thinking of representing nanoseconds since the big bang, the wait for 128-bit CPUs is not very long...

Re:Best aspects of C by shakna on Tuesday November 17, 2020 @02:23PM (#25128394)
GNU has extensions to support 128bit number types [0] already, for systems that can handle it.

[0] https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html

Re:Best aspects of C by jasonwatkinspdx on Tuesday November 17, 2020 @01:28PM (#25127552)
So, the problem is a 64 bit int only gives you ~500 years around the epoch at nanosecond resolution. That's sufficient for timestamping, but not great for a general purpose time library where even ordinary civil calculations might exceed that range, particularly in intermediate arithmetic.

Since larger than 64 bit ints are a disaster for portability, the reasonable solution is to go with a 64 bit signed seconds, 32 bit nano offset field. A lot of language std libs have adopted something along these lines.

DJB was advocating for everything to be in a format like this, referenced to TAI (UTC without leap seconds, basically). Sadly that didn't get any traction.

Re:Best aspects of C by ClumsyPilot on Wednesday November 18, 2020 @12:52PM (#25139902)
I remember in my University years i was astounded to find out that none of the programming languages we were taught could represent the Jurrasic period, or the day the earth was formed, as a date.

I was horrified even more when i learned that future leap seconds are undefined, and we literally can't tell what is the time on the clock lik3w a million seconds from now.

Re:Best aspects of C by marcosdumay on Tuesday November 17, 2020 @11:32AM (#25125676)
In what resolution?

What do people that need higher resolution use? And the people that don't care about that amount, do they pay the performance penalty?

Every physical or humane value is hard to some extent.

Re:Best aspects of C by fennecfoxen on Tuesday November 17, 2020 @02:42PM (#25128629)
This only really really works if you do TAI. Down with leap seconds.
Re:Best aspects of C by Gibbon1 on Wednesday November 18, 2020 @03:49AM (#25134503)
In my firmware I keep time as a 64 bit signed number that counts 32.768 khz ticks since the unit powered up. I think it'll roll over in 8 million years or something like that.

If you want to know what's broken? Most real time clock modules. They almost all want to store time as HH:MM:SS MM:DD:YY and sometimes 1/256 of a second but sometimes not.

Re:Best aspects of C by andi999 on Tuesday November 17, 2020 @10:45AM (#25125062)
the over-zealous compiler writers is getting a big problem. I remember a while ago there was a proposal of a friendly c standard.
Re:Best aspects of C by wool_gather on Tuesday November 17, 2020 @04:34PM (#25130187)
Indeed; by John Regehr: https://blog.regehr.org/archives/1180

I don't think it has really been proposed anywhere though, unfortunately.

Re:Best aspects of C by andi999 on Wednesday November 18, 2020 @12:07AM (#25133411)
I have been surmising there might be copyright issue of the actual standard?
Re:Best aspects of C by mrkeen on Tuesday November 17, 2020 @02:45PM (#25128670)
> The underlying cause is zero-terminated strings (instead of using start/end pairs or start/length pairs).

What type (and how big) should length be?

Re:Best aspects of C by masklinn on Tuesday November 17, 2020 @02:50PM (#25128737)
> What type (and how big) should length be?

size_t.

Re:Best aspects of C by mikepurvis on Tuesday November 17, 2020 @02:49PM (#25128726)
Probably something like how msgpack (or even variable length unicode encoding) works, where the low 127 bytes is a single uint8 char in place, and then the next 121 signals that a string of length 1-121 bytes follows, and then after that are a handful of sentinel values for "length follows and it's 1/2/4/8 bytes" plus maybe some special cases like zero-length string.

I can understand that this might have been too much implementation complexity/risk to contemplate 40 years ago, but this kind of pattern is very well established at this point, especially in scripting languages with loose typing.

Re:Best aspects of C by ncmncm on Tuesday November 17, 2020 @06:00PM (#25131081)
One word: strtok

It takes more code to use it correctly than to hand-code what you think it is supposed to be doing for you. strtok is Cursed.

strlcpy is similar. If you don't write that much more code, you are not using it correctly, and it is not giving you the value that is the reason you thought was why you were using it.

Re:Best aspects of C by jjav on Tuesday November 17, 2020 @08:28PM (#25132136)
> Also: String handling, which is responsible for so, so, so many security vulnerabilities.

That's not really a counter-example. Sure the string handling was an unfortunately choice but it is the standard. The standard library must implement it as defined. Being standard-compliant is not lack of polish.

Re:Best aspects of C by aw1621107 on Tuesday November 17, 2020 @08:56PM (#25132307)
Depends on what one means by "polished", I suppose. You can have a polished implementation of a not-so-polished specification, and vice versa.
Re:Best aspects of C by adamnemecek on Tuesday November 17, 2020 @11:23AM (#25125565)
> You can't even tokenize a string without either copying or modifying

rust-lang saves the day, yet again https://www.brandonsmith.ninja/blog/favorite-rust-function

Re:Best aspects of C by Jorengarenar on Tuesday November 17, 2020 @03:43PM (#25129551)
OK, updated
Re:Best aspects of C by hazeii on Tuesday November 17, 2020 @02:50PM (#25128739)
A single counter-example doesn't make it all wrong.

Perhaps a committee was involved.