Live data from Hacker News

It Can Happen to You

mattkeeter.com

161–170 of 419 posts

Re: It Can Happen to You

#161
post #13

It has been a hot minute since I've touched C, so I'm failing to grok the issue here. Sscanf is reading the data variable for a float-formatted string into a float variable. How is that also getting the size? What is different about strtof? It looks from the docs that it does something similar, just without using the formatting string.

Sscanf shouldn't need to get the size. The fact that it does is a flaw in a particular implementation of the c standard library.

Re: It Can Happen to You

#162

Earlier quoted context omitted.

All of the C++ algorithms list complexity guarantees, I believe. This saga stunned me to learn that C doesn’t seem to do this.

It's easy to forget that the original C standards were largely codifying existing practice during an era when using gets() [1] was existing practice. The world wasn't quite ready for Ada, I guess. Best-laid plans of mice and men etc. etc.. Also, keep an eye out for "amortized" complexity. This does have a legitimately rigorous definition, but for latency-bound paths it can practically amount to "O(whatever), except f…

It's also easy to forget that C was competing mainly with assembly, while C++ competed with managed languages. The early C programmer ethos, especially among library authors, was much more along the lines of "look at the generated object code if you want to know what it's doing" while modern practice leans more towards "read the documentation for complexity guarantees". I'm not saying that worse documentation leads to better programmers, but I'm not not saying that either. Practices change, standards change.

Re: It Can Happen to You

#163

Earlier quoted context omitted.

...I fully plan to use "O(whatever)". Not sure for what. But, yes. (naive) Quicksort's amortized complexity being O(nlogn), but its O(n^2) on already sorted data, is all I ever needed to learn to take away that lesson. When sorting already sorted data is worse than sorting randomized data, it's a quick realization that "amortized cost" = "read the fine print".

Quicksort as O(n log n) is not amortized complexity, but average runtime for random data.

Interestingly, it is quite easy to double the speed of Quicksort, even at this late date, with just a couple-line change.

http://cantrip.org/sortfast.html>

Anyway I thought it was interesting.

Re: It Can Happen to You

#164
post #129

Earlier quoted context omitted.

No, that's complete nonsense. Here's the latest revision of the standard: https://www.iso.org/standard/74528.html C has had a well-defined memory model since C11, I believe (re: "ordering of statements").

> ISO-C11 specifies 203 circumstances that cause undefined behaviors. 203 is enough to make almost every line of code questionable. The result of this is that looking at a simple 3 line C program and being asked whether the program terminates is undecidable without knowing which compiler was used. Null dereference for example is undefined behavior, and could cause a termination or not, depending on the implementation…

A good argument for compiling your debug builds with "-fsanitize=undefined".

Re: It Can Happen to You

#165
post #127

There's a bigger potential problem with the *scanf() functions than performance. They are inherently unsafe for reading numeric input. For example, if you do something like this: int n; sscanf("9999999999999999999999999", "%d", &n); the behavior is undefined. As the C standard says: > ... the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not a…

> Remember that in C "undefined behavior" [...] means that a conforming implementation can do literally anything. In the worst case, it will do what what you expect until it fails at the most inconvenient possible moment. Actually, the worst case possibility is that your program will become Skynet, enslave humanity for 10000 years, collapse all stars in the universe into black holes, and significantly accelerate proc…

It's even allowed for the program to change all extant texts of the Standard to indicate that its behavior is well-defined.

Re: It Can Happen to You

#166

Earlier quoted context omitted.

All of the C++ algorithms list complexity guarantees, I believe. This saga stunned me to learn that C doesn’t seem to do this.

It's easy to forget that the original C standards were largely codifying existing practice during an era when using gets() [1] was existing practice. The world wasn't quite ready for Ada, I guess. Best-laid plans of mice and men etc. etc.. Also, keep an eye out for "amortized" complexity. This does have a legitimately rigorous definition, but for latency-bound paths it can practically amount to "O(whatever), except f…

It makes me chuckle when hash maps are stated to be O(1) insertions. Which is true, in respect to the number of items in the map, assuming the map doesn't need resizing and there isn't a hash collision... but it's generally not true in respect to the key length. (I think most implementations are O(ln), where l is the length of the key and n is the number of inserted items, assuming the hash function is O(l) - the _amortised_ runtime would be O(l))

Re: It Can Happen to You

#167
Cool stuff mate! Searching for sscanf in github produces over 19 million results with over 15 million in C code. I bet there might be few cases where it could be replaced with something else... :) (not saying it's not useful function when used correctly)

Re: It Can Happen to You

#168
post #129

Earlier quoted context omitted.

No, that's complete nonsense. Here's the latest revision of the standard: https://www.iso.org/standard/74528.html C has had a well-defined memory model since C11, I believe (re: "ordering of statements").

> ISO-C11 specifies 203 circumstances that cause undefined behaviors. 203 is enough to make almost every line of code questionable. The result of this is that looking at a simple 3 line C program and being asked whether the program terminates is undecidable without knowing which compiler was used. Null dereference for example is undefined behavior, and could cause a termination or not, depending on the implementation…

> 203 is enough to make almost every line of code questionable. The result of this is that looking at a simple 3 line C program and being asked whether the program terminates is undecidable without knowing which compiler was used.

This is hyperbole to the point of being nonsensical.

> Null dereference for example is undefined behavior, and could cause a termination or not, depending on the implementation, even if it is known to be standards conforming to C11.

This sentence doesn't make any sense. If your C code has UB, it is wrong. The behavior of particular environments around certain UB is irrelevant to standards-conforming code, because standards-conforming code doesn't have UB.

Re: It Can Happen to You

#169
I think the only way I've avoided any of this is my academic work primarily deals with "write the performant, simulation codes in C++ or Fortran, write analysis in Python" (although others use matlab et al.) so everything parsing related has been through python, not C++, which ofc just has the "float()" type constructor. Generally, like most academics, I own my whole shop so fortunately no one uses my code other than one or two colleagues occasionally, so when bottlenecks arise I know where and what it is.

Re: It Can Happen to You

#170
post #156
post #129

Earlier quoted context omitted.

No, that's complete nonsense. Here's the latest revision of the standard: https://www.iso.org/standard/74528.html C has had a well-defined memory model since C11, I believe (re: "ordering of statements").

There is a standard, sure. But there are also a lot of compilers out there and I would bet that all but a few has either a "this compiles c11 except for [list of unimplemented features]" caveat or non-standard extensions.

> But there are also a lot of compilers out there and I would bet that all but a few has either a "this compiles c11 except for [list of unimplemented features]" caveat or non-standard extensions.

Your statement is broadly reasonable. Here's the GP:

> Shouldn’t we just come clean and admit to ourselves that there is no such thing as the C standard? There is a collection of loosely related languages that look similar and that collectively we call C, but really they’re all completely different and share almost no interoperability or common characteristics. And those standards that do exist provide almost no ability to reason about your code including things like ordering of statements.

It's just a string of incorrect statements, or at best, extreme hyperbole.

1. There is a C standard.

2. There's only one C language. Implementations differ, but not "completely," and are mostly interoperable. They all have in common the standard language, of course.

3. The C standard provides a fairly strong mental model for reasoning about code. Especially in later revisions, but even in C99. "Almost no ability to reason about" is false.

If you think C is fragmented or difficult to reason about, let me introduce you to Python (Python3, Jython, PyPy), Java (Oracle, OpenJDK, Dalvik), C# (Mono, .NET Core, .NET on Windows...), C++ (if you think implementing C99-C18 is hard, check out the stdlib required by modern versions of C++), etc.

Post reply on HN