I think this was silly, the author clearly does know C but they are complaining about optimizing compilers which do things "behind your back" and are becoming an increasing nuisance. It's sort of a passive aggressive "I think this should be an error but it isn't an error because twisted logic that the compiler uses with respect to undefined operation."<p>That people can teach themselves what to expect the compiler to do isn't all that surprising, and it also isn't surprising that a "modern" compiler does stuff an "old" C programmer might think is ridiculous.<p>I've engaged in this particular argument a few times only to throw up my hands in frustration over some exquisitely twisted line of reasoning that gave the compiler hacker person a fraction of a percent improvement[1] by exploiting this kind of situation. As long as I have a compiler flag that turns it all off its tolerable. But sheesh, sometimes I think these are C programmers who don't have the guts to become Rust programmers. You want to start fresh dudes, clean slate. Embrace it.<p>[1] "But Chuck, over the millions of machines out there its like an entire computer's worth of CPU cycles you can use for something else!"
Well apparently I do know C. If the author wanted to be as contrived a possible there are certainly more devious edge cases which could have been trotted out. The fact that e.g. the compiler may optimize out a NULL check <i>after</i> you've already dereferenced the darn thing shouldn't be surprising. Just fix your silly bug.
This reminds of me of the Quiz books that were popular years ago. They'd show some code that inadvertently tripped some obscure corner of the language.<p>Rarely did the quizzes provide great insight. Rather, they confirmed the benefits of keeping your code idiomatic.
Surprisingly accurate, author did his research.<p>5 is also missing a check for a NULL pointer. ;)<p>Most of there rules are unfortunately ignored, as obscure information. The worst offender I see in wild code is 5.<p>The second most ignored is not checking values before computation: 10, 11, 12.<p>No.7 is very interesting, rarely violated, most programmers don't even know that is a thing or just assume the processor won't trap on an unaligned read.
Although most comments use these examples to argue that C is a bad language, I would argue the opposite, that these examples show how C is an extremely useful language. C has occupied a niche position as the lowest commonly-used language that is both human-readable (at the level of expressing algorithms, data structures, functionality, and control flow) but not specific to any one instruction set architecture (and thus can compile to any architecture). Each C construct or statement maps efficiently into machine instructions, while not being an assembly language. I have trouble imagining how to make something like C any lower without becoming architecture-specific or cumbered with details that are more economically-suited for a compiler. But if too much higher, then the programmer becomes detached from this close relationship to the computer. The programmer can focus on implementing important speed & space performance details of an algorithm while not getting bogged down by more mundane details (such as register allocation, matching jump statements to their targets labels, keeping track of the return stack of a function, etc.) that are better suited for a compiler to handle. (That being said, I think Rust or something like it is a strong successor and can additionally express concurrency).<p>These examples illustrate well-intended and useful features of C, not flaws. I will explain why for each in a comment below:
> (especially C programmers)<p>Author needs to stop his anti-intellectual everyone-is-as-ignorant-as-me bullshit. I see that a lot re programming to justify a lot of silly positions. If you only know Javascript, that's great, I rather like having shiny things in my browser (I like it too much, even). That doesn't mean that C programming is obsolete; some of us know C. For example, I got #5 and #9 wrong, and the rest I got right including the general idea of the justifications. (10/12 is pretty good for someone who grew up in the Java era, but I want to get better.)
I'll readily admit that there are corners of C where I would not be able to tell you just what breaks. But I know about where they are and enough to stay away from them. If I'm not sure, the next guy won't be either.<p>I got 12/12 here. I would say I know C.
A trickier variant of #11 is to show people<p><pre><code> bool is_zero(int x) {
return x == -x;
}
bool is_zero(float x) {
return x == -x;
}
</code></pre>
and ask them which is wrong and for what value. Most of the time the instinctive response is that it must be the float code (because floats are evil, duh).<p>This works even in languages with defined overflow for integers.
1.<p><pre><code> int i = 10;
</code></pre>
Q. Is this code correct?<p>A. Yes.<p>2.<p><pre><code> extern void bar(void);
void foo(int *x)
{
if(x == NULL)
{
return;
}
int y = *x;
bar();
return;
}
</code></pre>
Q. It turns out if you check the validity of your variables before you use them it prevents you from having to understand undefined behavior.<p>A. Is there a question here?<p>3. There was a function:<p><pre><code> #define ZP_COUNT 10
void func_original(int *xp, int *yp, int *zp)
{
int i;
for(i = 0; i < ZP_COUNT; i++)
{
*zp++ = *xp + *yp;
}
}
</code></pre>
I optimized it this way:<p>...because nobody had any idea what it was doing and so it wasn't used anywhere.<p>4.<p><pre><code> double f(double x)
{
assert(x != 0.);
return 1. / x;
}
</code></pre>
Q. Is it possible for this function to return inf?<p>A. If you're at the point where you're asking that question you should have been using a decimal library a long time ago.<p><pre><code> int my_strlen(const char *x)
{
int res = 0;
while(*x)
{
res++;
x++;
}
return res;
}
</code></pre>
Q: The provided above function should return the length of the null-terminated line. Find a bug.<p>A. They didn't use `strlen()`.
Why the heck was the name of this post changed? It rather conveniently puts the author in a better light by downplaying the anti-intellectual nature of the article I commented about above. I thought the general rule was that posts should be titled with the title of the linked article, which was the case before but now is not the case.<p>EDIT: To answer my own question, the submitter is clearly the author based on his submission history. So yes, this was an act of self-censorship to try to hide the author's disgusting attitudes.
5 is IMO nothing else than nitpicking. 2 and 4 (and maybe 6) might have some importance in real life, while others are easy and kinda expected (although comma operator in 8 might not be known to less experienced programmers). I can't really see the point of this article other than "hey, do you remember that there is a concept called undefined behavior in C?".
I was so surprised by the first question that I actually tried it on my computer...<p>Am I the only one who tried compiling :<p>#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int i;
int i=10;
printf("i=%d\n", i);
return 0;
}<p>and got the redeclaration error I expected?
I just got the first one wrong and haven't written C code in a decade. I have to admit I haven't seen that construct used in any programs. I guess, no harm no foul, but still seems like an odd construct to allow.
I realize this has probably been asked, but anyone recommend good resources for learning C? And not necessarily just the legendary textbooks, but any clever tutorials or fun learning resources? Thanks!
Does anyone know of a tool which can automatically scan source code for these types of oversights?<p>Assuming of course the compiler doesn't already check for all of these...
He's discussing subtle points of the C language and yet there is no mention of which compiler he's using, whether the results might be different for different compilers, hardware platforms, and how they correlate with multiple C standards (C89, C99, C11/C1X, etc).<p>He succeeded in convincing me that he does not know C!
Already the first example is wrong. So I stopped reading.<p>% cc -std=c11 -o dingens dingens.c
dingens.c:6:9: error: redefinition of 'i'
int i = 10;
^
dingens.c:5:9: note: previous definition is here
int i;
^
1 error generated.
% cat dingens.c<p>#include <stdio.h><p>int main()
{
int i;
int i = 10;<p><pre><code> printf("hello, world\n");
return 0;</code></pre>
}<p>%