5 ms·
It dates to the first standardization of C in 1989. The "C as portable assembly" view ended when ANSI C got standardized, and K&R's 2nd edition was published.
by SAI_Peregrinus 3y ago
It dates to the first standardization of C in 1989. The "C as portable assembly" view ended when ANSI C got standardized, and K&R's 2nd edition was published.
- j16sdiz 3y agoI would argue it's the modern understanding of C standard is flawed. Back in 89, many of those unspecified behavior were understood as implementation/hardware dependent, not undefined. Aliasing was the norm, `restrict` was actually a keyword. Modern C is neither safe nor low-level.
- jcranmer 3y agoAscertaining the state of the mind of the C committee in 1989 is difficult, since only the documents from ~late 1996 are consistently available online (the earlier documents are probably sitting somewhere in a warehouse in Geneva, but they may as well not exist anymore). But definitely by the time C99 came out, it is clear that optimize-assuming-UB-doesn't-happen was an endorsed viewpoint of the committee [1]. C99 also added restrict to the language (not C89 as you suggest), and restrict was the first standardized feature that was a pure UB-optimization hint [2]. It is important to remember that there isn't just one catch-all category of implementation-varying behavior. There is a difference between unspecified behavior, implementation-defined behavior, and undefined behavior. Undefined behavior has been understood, from its inception, as behavior that doesn't constrain the compiler, and often describes behavior that can't be meaningfully constrained (especially with regards to potentially-trapping operations). [1] The C99 rationale gives an example of an optimization that compilers can perform that relies on assuming UB can't happen--reassociation of integer addition, on one's complement machines. [2] The register keyword is I believe even in K&R C and would also be qualified as a compiler hint feature, but I note that it prohibits taking the address of the variable entirely, so it doesn't rely on UB. Whereas restrict has to rely on "if these two variables alias, it's UB" to allow the compiler to optimize assuming nonaliasing.
- Someone 3y ago> Back in 89 […] `restrict` was actually a keyword. Was it? I thought it’s more recent. https://en.wikipedia.org/wiki/Restrict https://en.wikipedia.org/wiki/Restrict seems to agree (“In the C programming language, restrict is a keyword, introduced by the C99 standard,[1] that can be used in pointer declarations”), as does https://en.cppreference.com/w/c/language/restrict https://en.cppreference.com/w/c/language/restrict (“restrict type qualifier (since C99)”) Was there an older usage?
- rsaxvc 3y agoI've used several pre-C99 embedded compilers that supported restrict. IIRC, probably of mid 90s vintage.
- 6D794163636F756 3y agoI haven't gotten to use C in industry, but I was taught that undefined behavior just means that it is defined by the running system and not the compiler. Is that not the general understanding? Maybe I was just taught that way because it was old timers teaching it.
- dale_glass 3y agoNo. See this for details on how UB is handled by compilers: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-... The TL;DR is that compilers compile code based on assumptions that UB won't be invoked. This sometimes produces extremely surprising results which have nothing to do with the hardware/OS.
- School-Cotton 3y agoThat’s indeed incorrect. Undefined behavior anywhere means that the entirety of your program is undefined and may do anything.
- patrakov 3y agoWhat you are talking about is implementation-defined behavior. It exists in the C standard separately from the undefined behavior.
- SAI_Peregrinus 3y agoImplementation Defined behavior means the standards authors provided a list of possible behaviors, and compiler authors must pick one and document which they picked. Unspecified behavior is more what you're thinking of, though in that case the standard still provides a list of possibilities that compiler authors have to pick from, they just don't have to document it or always make the same choice for every program. There's no allowed subset of behavior where compiler authors are free to pick whatever they want and document it (but must do so). IMO there should be, most "Undefined Behavior" could be specified and documented, even where that choice would be "the compiler assumes such situations are unreachable and optimizes based on that assumption" like much of current UB. At least it'd be explicit!
- circuit10 3y agoFor C to be portable this needs to be undefined behaviour because there are CPUs that don’t support unaligned access
- chaboud 3y agoThat’s why, while much of the linked blog is kind of off the mark (signs of someone knowing less than they think they know), the general conclusion, using aligned pointers is recommended, is one that I typically recommend to developers new to C or C++ anyway. I’m alright with folks sticking to aligned pointer operations, largely for performance reasons. On some platforms, unaligned operations are really expensive.
- saagarjha 3y agoI know the author. Your guess here is wrong.
- astrange 3y agoThere are some other reasons, but that's one of them. Another is that you want to guarantee objects are stored aligned in memory because that gives you some free bits in pointers you can hide stuff in. (This has less hardware support than it should.)
- Dylan16807 3y agoIt doesn't need to be undefined to say it crashes on some architectures.
- circuit10 3y agoI guess it could also be implementation defined My point here is that you can’t have “everything works as it does in the native assembly language” and “portable assembly” at the same time because if you rely on implementation defined or undefined behaviour then it’s not portable any more
- 3y ago