9 ms·
Who Says C is Simple? (2010)
- dang 12y agoCan anybody figure out the year on this one? Internet Archive says 2011 but it seems it might be earlier.
- pjscott 12y agoThe HTTP headers can put an upper bound on the date: Last-Modified: Fri, 29 Oct 2010 16:59:15 GMT And the changelog for CIL suggests that it may be significantly older: http://www.eecs.berkeley.edu/~necula/cil/changes.html http://www.eecs.berkeley.edu/~necula/cil/changes.html
- dang 12y agoThat header trick is a good one. Ok, we'll put 2010 on it even though it is likely quite a bit older. An upper bound is better than nothing.
- mmozeiko 12y agoThis URL http://www.eecs.berkeley.edu/~necula/cil/cil002.html#toc1 http://www.eecs.berkeley.edu/~necula/cil/cil002.html#toc1 mentions cil version 1.3.7. Changelog http://www.eecs.berkeley.edu/~necula/cil/changes.html http://www.eecs.berkeley.edu/~necula/cil/changes.html says 1.3.7 was released on 2009-04-24.
- dang 12y agoBut 2010 may just have been when they stopped updating a version number. It looks like early 2000s material to me, based on nothing in particular. There's also this: When I (George) started to write CIL I thought it was going to take two weeks. Exactly a year has passed since then and I am still fixing bugs in it The CIL paper was published in 2002. Actually the whole project looks interesting—arguably more so than the currently posted page. It should have its own HN thread sometime. https://news.ycombinator.com/item?id=836735 https://news.ycombinator.com/item?id=836735 was a while ago!
- bjwbell 12y agoFYI the project is still active, https://github.com/cil-project/cil https://github.com/cil-project/cil That website for it hasn't been updated.
- Moral_ 12y agoThe first two invoke UB and are thus completely illogical.
- barrkel 12y agoNo they don't. What UB do you think they invoke? They do invoke implementation defined behaviour, but not undefined.
- deleted 12y ago[deleted]
- DSMan195276 12y agoAn uninitialized variable is UB, not implementation-defined. Thus, the compiler is free to treat the variable as though it doesn't have a value at all, or change it's value at will. It's not uncommon for the value of an uninitalized variable to change at strange places in the code that you wouldn't expect, because the compiler initially said "Variable x will be kept in register %eax", but then without a value to initialize it too, it just uses whatever happens to be in %eax at the time. For example, if they compiled this: return x == (1 && x); Into this: movl $0, %eax andl $1, %eax cmpl %eax, %eax # Result in %eax That will (obviously) return 1 every time, because we compare %eax and %eax. The reason for this is that the value of 'x' changes half-way through the computation (Because the computation is done in %eax, which is where 'x' is assumed to be). This is valid because 'x' is uninitalized, so it doesn't have a defined value.
- barrkel 12y agoWhat evidence do you have that it's an uninitialized variable? It's a code fragment; it's not in a function body. The way I read it, it was simply to document the type of x. 'x' could be a global for all we know.
- DSMan195276 12y agoMy evidence is that the entire page is basically just to shows CIL's output on various pieces of code, and CIL's output is linked on the page and looks like this: /* Generated by CIL v. 1.3.7 */ /* print_CIL_Input is true */ #line 1 "cilcode.tmp/ex30.c" int main(void) { int x ; { #line 2 return (x == (x != 0)); } } From that I think it's safe to say that it's talking about 'x' being an uninitialized variable in a function (Because that's what they put into CIL). This code definitely has the issue from UB that I described above.
- agounaris 12y agowho said C is simple? :S
- pavanky 12y agoIt is fairly simply if you understand how the data types and data structures are laid out in memory. The problems are with the corner cases like he mentions at the beginning of his post.
- EpicEng 12y agoC is simple, but that doesn't mean it's not powerful, and with power comes... yada yada yada. There are many edge cases to be sure, but as a language, its constructs and features are very simple.
- kd0amg 12y agoA lot of people have said it. They develop a mental model that is a rough approximation of its semantics, see that their mental model is simple and conclude that the semantics itself must also be simple. Then other people write articles like these to remind the first group that their "simple" mental model is not the actual semantics, just an approximation.
- userbinator 12y agoAfter looking at the JavaScript/ECMAscript standard, or even C++, C feels positively trivial in comparison.
- deleted 12y ago[deleted]
- taeric 12y agoWho says simple things always yield simple results?
- cbd1984 12y agoDepends on how you define simple: If something is simple for the compiler-writer, then simple things do yield simple results. If something is simple for the programmer, simple things often yield quite complex results. For example, in a language that's simple for the compiler-writer, (1/10) times 10 is only very rarely 1. 0 is a common answer, as is some fraction which is almost, but not completely, unlike 1. In a language which is simple for the programmer, Heaven, Earth, and minor deities will be moved to make (1/10) times 10 come out to the obvious, simple answer.
- taeric 12y agoIt really only depends on if you define simple as "can only derive simple results." And, you do realize that one of the simplest languages for compiler writers, lisp, doesn't have to move heaven/earth to make that calculation work out how you want it.
- copsarebastards 12y ago> And, you do realize that one of the simplest languages for compiler writers, lisp, doesn't have to move heaven/earth to make that calculation work out how you want it. I've written a C compiler and am currently writing a Lisp compiler, and I'm not sure where you get the idea that Lisp is a simple language for compiler writers. Lisp's simple representation belies a very complicated runtime, to the point that the majority of Lisp implementations don't support compilation at all--they're interpreted only.
- taeric 12y agoThis seems to get back to the other debate that crops up with "simplest." Just because I posit that it is one of the simplest languages, does not mean I imply it is by definition simple.
- cbd1984 12y agoC is simple to compile into nearly-optimal code, or at least it was back in the 1970s, when computers had single-opcode dispatch or trivial pipelines, no SIMD hardware, no other parallelism worth mentioning, and it wasn't worth worrying about cache too much. (Running in the registers was a neater trick.) That meant it was relatively simple to 'see' the assembly language 'behind' a given C function or stretch of code; it didn't take much to get inside the head of a C compiler, so you could be reasonably sure that a simple piece of C would result in a similarly simple piece of assembly out the other end. That, of course, was well and good when it was reasonably simple to predict actual performance from glancing at assembly code, which assumes opcode performance (as opposed to, say, cache performance) dominates how fast the code runs. Now... how many of those things still hold true on desktop and server class hardware?
- revelation 12y agoBut everything that came after C hasn't improved on this, at all. In fact, languages now dominate that aren't compiled. So as it stands, C is still your best bet when you are looking for that optimal translation. Intel has recently made some effort to augment it in ways to fully utilize new CPUs various parallel pipelines and specific functionality: https://ispc.github.io/ https://ispc.github.io/
- yoklov 12y agoISPC is cool, what it helps out with (writing the SIMD kernel) has never really been the bottleneck in my experience. The data still has to be arranged optimally for the hardware in order for SIMD code to have any benefit (and at this point, writing SIMD code is straightforward). You also still need to be experienced with the capabilities of the hardware if you have any chance of writing good ISPC code (although this is true of C, as well as any shading language). That said, using it to target SSE and AVX with the same code is attractive.
- GFK_of_xmaspast 12y ago"C is simple to compile into nearly-optimal code, or at least it was back in the 1970s," And yet the best practice of the time was not to use C for time-critical applications. If your hypothesis were true, why would, say, all those NES programmers write all that assembly?
- copsarebastards 12y agoAll of the examples here are really horrible code. This is the second article in a few days on Hacker News to list out a few examples of how hard C is. And for little reason; there's absolutely no value in being able to write something like: return ({goto L; 0;}) && ({L: 5;}); It probably has a bug, will be hard to debug, and isn't more performant than writing it in a clearer way. And unfortunately, while the examples here are probably all contrived, there are plenty of real-life cases where code as bad as this gets into production systems. So why are we still writing code like this? The answer is reverse compatibility. Not just of compilers, but of tools and skillsets: people are unwilling to support multiple versions of C and want their code to run forever. Objective-C and C++ do things to add functionality to C, but they don't remove the functionality of C that allows these kinds of problems. This points to a need for a new language that avoids these issues. I think Rust is the answer, but I would like to see more languages try to fill that gap--competition is healthy.
- pjmlp 12y ago> This points to a need for a new language that avoids these issues. They already existed back when C was UNIX only, but then UNIX became widespread....
- Karliss 12y agoThis is odd, GCC documentation clearly states that jumping into statement expression is not permitted. It is properly identified as error when compiling as c file, but no errors are given when compiled as c++ file. https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
- sclangdon 12y ago> This points to a need for a new language that avoids these issues. I think Rust is the answer, but I would like to see more languages try to fill that gap--competition is healthy. Programs written in C and C++ may have issues because the languages assume the programmer knows what they are doing. This assumption leads to some great solutions to hard problems because the programmer is essentially free to do what they want. Of course, this assumption, as with most others, doesn't always hold true. This doesn't mean there is a problem with the language. The problem is with the programmer. If you're going to write something like "return ({goto L; 0;}) && ({L: 5;});", no language is going to save you. C and C++ are still used today, in part, because modern languages try to restrict the programmer. Rather than assume the programmer knows what they are doing, they assume the programmer is stupid and needs help to cross the road. By assuming stupidity, the restrictions modern languages put in place prohibit certain solutions and as such C and C++ will remain the go-to systems languages. We do not need new languages. What we need is programmers who won't abuse the languages we already have.
- iopq 12y agoI've been looking for this for months, I wanted to link this to my friend who said he prefers C to Java for his CS classes.
- tdsamardzhiev 12y agoCome on, almost any language I can think of is a better fit for CS classes than Java.
- iopq 12y agoBut get this, he said Java was HARD. Compared to C?
- kazinator 12y agoI stopped reading after the explanations about return ((1 - sizeof(int)) >> 32); Unless size_t is wider than 32 bits, it has undefined behavior. That's why it returns 0; it could as well be 42, or the program could terminate with or without a diagnostic message, etc.