News for hackers. Stuff that matters.
Re:Learn C The Hard Way by rpearl on Saturday July 02, 2011 @10:32PM (#2722875)
Do people really think C is some mysterious, inscrutable language?

"To many programmers, this makes C scary and evil."

Is this actually true for people? I find C code generally very easy and straightforward to understand; there's not any magic behind the scenes, like there is in any language that's more "high level" than C.

Re:Learn C The Hard Way by zedshaw on Saturday July 02, 2011 @10:47PM (#2722913)
Yes, actually people are deathly afraid of C thanks to other language inventor's excellent marketing against it. There's a few things that you need to really nail to be good at C, and they're difficult things, but it's not "dangerous" like people keep claiming.
Re:Learn C The Hard Way by irahul on Saturday July 02, 2011 @11:17PM (#2722985)
C is difficult, yes. Dangerous - I don't know in what sense. I manage to get more exceptions in my Python, Ruby code, owing to undefined variables or incorrect types, than I get segfaults in C.

The main issue with C is it takes some time before you are ready to take it head on. An experienced C programmers would have his repertoire of generic data structures library with time complexity guarantees (programs without hashes, expandable lists and operations on them are a pain), will know how to properly use function pointers to do that dependency injection thing other programmers are raving about, separate interface from implementation, know the build environment, know how to use structures and function pointer to build abstractions etc.

But before that, C takes much work to produce little. For someone starting programming, the learning curve is steep. Or more like, the gratification is really, really delayed. It takes some time before he can take on a real world project(it does in the high level languages as well, but the initial progress is faster).

Re:Learn C The Hard Way by antirez on Sunday July 03, 2011 @09:43AM (#2723667)
what I keep repeating about that is why the C standard guys don't freaking update the libc with a new version of the C standard? Deprecating the old silly stuff like strcat() (the libc is full of bad calls) and adding lists, hashes, btrees, good dynamic strings lib, and so forth. An huge step forward for C... without even touching the core language.
Re:Learn C The Hard Way by irahul on Sunday July 03, 2011 @04:57PM (#2724581)
A bit OT and not sure if you will see this.

Seeing that you are the guy(or onof the guys) behind redis which is written in C, do you have any recommendations for generic data structures and operations on them?

I personally have a trivial vector implementation which resizes when full, and a red-black tree implementation for associative arrays. Both of them work fine for my purpose - does the job, good locality of reference, generic over void*.

I have seen glib but largely neglected it because I only need a very small part of it.

Re:Learn C The Hard Way by burgerbrain on Sunday July 03, 2011 @06:45PM (#2724809)
Git is a good place to rip that kind of stuff out of.
Re:Learn C The Hard Way by praptak on Sunday July 03, 2011 @09:17AM (#2723637)
"I manage to get more exceptions in my Python, Ruby code, owing to undefined variables or incorrect types, than I get segfaults in C."

What happens when you don't get a clean segfault is what got C the "dangerous" reputation.

Re:Learn C The Hard Way by irahul on Sunday July 03, 2011 @04:52PM (#2724564)
If you are developing, `gcc -g` while compiling(or CFLAGS += g), and loading the core with gdb does give a very good idea of what went wrong.
Re:Learn C The Hard Way by praptak on Sunday July 03, 2011 @05:11PM (#2724615)
It is a lucky scenario when you actually get a core and one taken at the exactly right time. Unfortunately there are some pointer bugs that are hard to find even with Valgrind.

Buffer overflows do not produce cores, they just sit there until a determined cracker makes use of them. And a dangling pointer might still access memory that looks valid both to OS and memcheck.

Re:Learn C The Hard Way by JoshTriplett on Sunday July 03, 2011 @12:10AM (#2723051)
The negative connotations of the word aside, it seems perfectly reasonable to call C dangerous. Without that "danger", you couldn't write an OS kernel, a language runtime, or various other low-level code we need on our systems; on the other hand, when writing higher-level code that doesn't need that level of raw access, it seems useful to remove the possibility of a broad class of mistakes.

See also Rusty Russell's rules about "easy to use versus hard to misuse". I find C easy enough to use, but also easy to misuse.

Re:Learn C The Hard Way by burgerbrain on Sunday July 03, 2011 @03:28AM (#2723283)
"Danger" minus the negative connotations is best pronounced "power".
Re:Learn C The Hard Way by cturner on Sunday July 03, 2011 @05:33AM (#2723414)
gets()?
Re:Learn C The Hard Way by burgerbrain on Sunday July 03, 2011 @11:56AM (#2723887)
With great power comes great responsibility. ;)
Re:Learn C The Hard Way by ramidarigaz on Saturday July 02, 2011 @10:41PM (#2722897)
Many of the friends I made in my CS classes were terrible with pointers. I never really understood why they didn't grasp pointers, but it was a major stumbling block for them in C/C++
Re:Learn C The Hard Way by cturner on Sunday July 03, 2011 @05:54AM (#2723435)

    I never really understood why they didn't grasp pointers
The root of the problem is the language designers' loose use of star. "star something" is contained in a phrase that means one thing at declaration, "star something" has a different meaning the rest of the time.

    #include <stdio.h>
    void eg(int i) {
        int *j = &i; // "huh? Put the address of i into *j?"
        *j = *j + 1;
        printf("%d\n", *j);
    }
    int main() {
        eg(4);
    }
With more detail. In the line..

    int *var = something;
.. the system assigns to the pointer. Yet in..

    *var = 6;
.. it assigns to the contents of the pointer.

Common usage creates further room for confusion:

    int *var; // <- this is what people write
    int* var; // <- instead of this
If they'd made the syntax ".int var", and then used * solely for dereferencing, people wouldn't have these problems learning pointers. Consider

    #include <stdio.h>
    void eg(int i) {
        .int j = &i;
        *j = *j + 1;
        printf("%d\n", *j);
    }
    int main() {
        eg(4);
    }
Further confusion comes from (1) special arrangements around string declaration and (2) printf use of %s to expect a string pointer when %d and %f expects (non-pointer) simple int and simple float.

    char* something = "huh? so now this does goe into *something?";
Re:Learn C The Hard Way by roel_v on Sunday July 03, 2011 @10:19AM (#2723725)
That's because of the (visually) 'wrong' use of * (wrong in the sense that it's unintuitive). The key is that * is part of the type of the declaration, not of the variable; an int* is not an int. So

  int *j = &i;
is more correctly expressed and easier to understand when written like

   int* j = &i;
The only reason to put the * in front of the variable name is when declaring several pointers in one line. So the solution is to only use it that context, or not doing it at all.
Re:Learn C The Hard Way by alecbenzer on Sunday July 03, 2011 @10:14PM (#2725143)
This bothers me so much about C/C++ syntax. int* a, b; should clearly declare two int pointers, not one int pointer and one int.

Stroustrup wrote something somewhere where he explained that int* a; is more appropriate for use in C++ because C++ is supposed to be more focused on types, and int * a; is more appropriate for C because of something about C's philosophy, but I can't remember what. I wish they would have changed the syntax for C++, but I guess he couldn't have while still keeping C++ a superset of C.

edit: found it: http://www2.research.att.com/~bs/bs_faq2.html#whitespace

"A ``typical C programmer'' writes ``int p;'' and explains it ``p is what is the int'' emphasizing syntax, and may point to the C (and C++) declaration grammar to argue for the correctness of the style. Indeed, the * binds to the name p in the grammar.

A ``typical C++ programmer'' writes ``int* p;'' and explains it ``p is a pointer to an int'' emphasizing type. Indeed the type of p is int*. I clearly prefer that emphasis and see it as important for using the more advanced parts of C++ well."

Re:Learn C The Hard Way by atakan_gurkan on Sunday July 03, 2011 @09:44AM (#2723672)
To avoid this sort of thing, I use:

    #include <stdio.h>
    void eg(int i) {
        int *j; // "j is a pointer and (hence) *j is an int"
        j = &i; // "Put the address of i into *j? Yup"
        *j = *j + 1;
        printf("%d\n", *j);
    }
    int main() {
        eg(4);
    }

Perhaps this is because I am just used to it, but I really see very little room for confusion here. The common usage avoids confusion, if you do not insist on assignment at the time of declaration.

To address your second confusion, just keep in mind that strings are char arrays and an array's name is actually a pointer. Again, I find this very straightforward.

Re:Learn C The Hard Way by cturner on Monday July 04, 2011 @06:34AM (#2726111)

    I really see very little room for confusion here.
I don't understand how you reach that conclusion. You might understand it, I don't see how you can say there is very little room for confusion.

Yes, if you know about declaration follows use, it makes sense.

Yes, if you "keep in mind that strings are char arrays and an array's name is actually a pointer" then it makes sense.

You can get by by knowing to avoid some constructs.

If you know how the c compiler works, pointers make sense.

If you know C then you know C.

But when you're new to the language, you don't know these things and that's what this part of the thread is discussing.

Another responder wrote:

    The key is that * is part of the type of the
    declaration, not of the variable; an int* is
    not an int.
The grammar is structured as though it's not. Consider this:

    int* c, d;
Since star is part of the type, if the language was designed well then both of them would be int pointers. But in that case, only c is. d is an int. Awful.
Re:Learn C The Hard Way by atakan_gurkan on Monday July 04, 2011 @09:34AM (#2726489)
>> I really see very little room for confusion here.

> I don't understand how you reach that conclusion. You might understand it, I don't see how you can say there is very little room for confusion.

Please do not put words in my mouth. I wrote "I see very little room for confusion" not "There is very little room for confusion". I tried to make it clear that I was talking about my personal experience; and I was talking about my personal experience since I was hoping it would help, not to defend the syntax of C.

Sometimes a particular point of view allows you to understand something; in some cases it makes the previously mystifying point "trivial" or "obvious". I am sorry that the POV that helped me so much does not help you at all.

Re:Learn C The Hard Way by cturner on Monday July 04, 2011 @09:45AM (#2726518)
I see, and thanks for clarifying.

The point of my earlier post was to describe strong reasons for people to have trouble with pointers.

Re:Learn C The Hard Way by Goladus on Monday July 04, 2011 @08:16AM (#2726292)
> if the language was designed well

Do you mean to reinforce that the language is not beginner-friendly, or are you really asserting that makes the language poorly-designed? If it's the latter, you should really at least explore some other factors before making the conclusion. It seems to me that it's a relatively minor distinction once you know it, so from a design perspective that may simply be a tradeoff for some other advantage.

Re:Learn C The Hard Way by cturner on Monday July 04, 2011 @08:47AM (#2726380)

    Do you mean to reinforce that the language is not
    beginner-friendly, or are you really asserting that
    makes the language poorly-designed? 
I was seeking to account to ramidarigaz why his CS classmates didn't understand pointers.

I think poor grammar is poor design - i.e. part of the type affects both variables (int), the other part doesn't (star).

The other issue is use of star to in one place to mean create reference, in others to mean dereference. That was the focus of my first post.

    from a design perspective that may simply be a
    tradeoff for some other advantage.
I've yet to see evidence of any. What sort of things were you thinking about?
Re:Learn C The Hard Way by endgame on Monday July 04, 2011 @02:44AM (#2725627)
If you remember that the experiment here was to make declaration follow use, it makes sense. I consider it a failed experiment, but it does make sense.
Re:Learn C The Hard Way by alderssc on Saturday July 02, 2011 @10:54PM (#2722935)
I would hazard to guess its due to two things: 1) a lack of understanding about how the machine works, and in particular the way the memory is organized; and 2) lack of explanation of why anyone would need to use pointers. Introducing pointers in the context of a linked list, or explaining call-by-reference would probably help make things more concrete.
Re:Learn C The Hard Way by younata on Sunday July 03, 2011 @01:44AM (#2723174)
I have friends who had to take an intro to C++ as their first (and only) programming class.

I heard them talking about passing arguments to functions as "call by reference" many times, and it was obvious they had no idea what they were talking about, just regurgitating what the instructor said.

Re:Learn C The Hard Way by gregjor on Sunday July 03, 2011 @02:28AM (#2723225)
K&R chapter 5.5, Character Pointers and Functions, explains pointers and shows how they are used in C. It's probably the clearest explanation of pointers ever written, and it doesn't require any understanding of hardware or assembly language (though that would help).

I remember reading those three pages over and over and experimenting with the code until I got it. I probably spent several days studying the pointer chapter back when I was a teenager. The light bulb eventually went on and C pointers made sense -- until learning C my programming experience was mainly with time-shared BASIC. The stepwise refinement of an indexed array version of strcpy() to a pointer-based version is a masterpiece of programming writing -- I still refer programmers I am mentoring to that chapter.

Finishing the strcpy() example with the one-liner

  while (*s++ = *t++) ;
the authors write "Although this may seem cryptic at first sight, the notational convenience is considerable, and the idiom should be mastered, because you will see it frequently in C programs." I've found that programmers either get that line of code or they don't, and those who don't haven't mastered their craft.
Re:Learn C The Hard Way by eropple on Sunday July 03, 2011 @03:35AM (#2723291)
Getting it or not is one thing, but I'd advocate keelhauling anyone who wrote that sort of thing in production.

The "notational convenience" is more obnoxious than anything. But, then, I'm not particularly a fan of terseness for the sake of being terse.

Re:Learn C The Hard Way by gregjor on Sunday July 03, 2011 @05:03AM (#2723381)
I'm not a fan of wordiness for the sake of being wordy. If you think the code is terse just to show off you are missing the point. There's a difference between writing obscure code and writing concise idiomatic code -- see "The Elements of Programming Style" by Kernighan and Plauger. I'd rather Kernighan, Ritchie, Thompson, Pike, et al. write my production code than someone who thinks C pointer idioms are a punishable offense.

"That sort of thing" has been in production in the C libraries, the UNIX kernel, and all of the brilliant utilities that make up UNIX for over 30 years. It's also very much in production code at Google.

You might want to read Paul Graham's thoughts on succinct code at http://www.paulgraham.com/power.html and Rob Pike's "Notes On Programming in C" at http://doc.cat-v.org/bell_labs/pikestyle.

Re:Learn C The Hard Way by eropple on Tuesday July 05, 2011 @08:22PM (#2732098)
I've read both of those links in the past, thanks. And while, yes, "idiomatic" (read: terse and annoying) code is in use in all those areas, I don't have to see it.

Code should be pleasant to read wherever possible. That simply is not, to my mind, pleasant to read. It's one step away from Perl line noise (which I avoid, too). You may disagree with this, and that's fine--different strokes for different folks. I have no interest in seeing it in code I have to maintain; you might, and that's OK by me.

(To be fair, however, I have little interest in working with or, god forbid, maintaining C or C++ code under any circumstances. They press the buttons of a group of developers to which I don't belong.)

Re:Learn C The Hard Way by nitrogen on Sunday July 03, 2011 @05:11AM (#2723389)
I imagine terseness was a lot more valuable when everyone was programming on an 80x25 (or smaller) terminal or even punch cards. I've seen a few examples of code like this from early libc implementations of functions like strcpy, malloc, etc. Take a look at the source code of BSD libc -- some of that stuff is historic.

I myself never got much into the terseness game, since apart from a brief stint using gwbasic and later QuickBasic at 80x25, I learned programming using DJGPP in DOS with the RHIDE IDE. The IDE could trick the VGA into displaying something like 132x60, leaving plenty of room for descriptive code.

Re:Learn C The Hard Way by gregjor on Sunday July 03, 2011 @05:39AM (#2723417)
The Go language tutorial and examples look right at home alongside K&R. Likewise jQuery and other Javascript libraries, where terseness is valued due to bandwidth rather than screen size.

The idiomatic C style is so natural to me now I don't see it as a defect to fix or a game I'm playing. It's how I learned to program in C because I learned from K&R, and if they aren't the authorities I don't know who is. When I see wordy and bloated Java-style code it reminds me of the years I spent writing COBOL. Ultimately, though, it's not efficiency or a desire to show off or confuse other programmers that influences my style. To me code that does what it needs to with no extra fluff is beautiful.

When I see

  while (*s++ = *t++) ;
I know what it does -- I don't need any comments or "descriptive" variable name or an explicit test for a null byte to make it clearer. If a programmer comes across a line of code that he or she doesn't understand the fault may be with the author, but it may be with the reader. In my experience there are a lot of unskilled programmers who quickly decide that any code they look at is badly written and should be thrown out. I don't think I should dumb down my code just so programmers less fluent with C can understand it. I have to consult a dictionary sometimes when I read Cormac McCarthy or Nabokov but I don't think they should write with easier words for my sake.
Re:Learn C The Hard Way by rat on Sunday July 03, 2011 @08:04AM (#2723550)
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." --Brian Kernighan Not to mention people aren't as smart as you debugging/understanding it. Also that code relies on the order of operations which I wouldn't recommend outside of math because it can be confusing. And it doesn't check that s isn't null.

Java is considered verbose for a number of reasons. It has a number of variable modifiers, it uses long names(which are generally good but can be stupid, especially in some cases of identifying multiple abstraction levels), and because it lacks type inference for generics and collection literals. c frequently makes the opposite mistakes with tiny cryptic or non whole word names. C lacks generic programming, it does do a decent job with initializers but unfortunately those can only be used at initialization.

Re:Learn C The Hard Way by gregjor on Sunday July 03, 2011 @01:32PM (#2724095)
The point of the example is to explain pointers by starting with a more familiar concept: indexed arrays. It would help if you were referring to the book; the authors note more than once that "the programs are intended to be illustrative, not bullet-proof."

Understanding the precedence and order of evaluation of operators is fundamental to mastery of any programming language (chapter 2.12 in K&R). All C code must "rely on" the order of operations, and if an indirect assignment through a pointer with post-increment is confusing... well that's the point I was making in the first place.

Re:Learn C The Hard Way by rimantas on Sunday July 03, 2011 @11:18AM (#2723811)
Good quote, but there is nothing particularly clever in the line above. It is in the same league as if (something) or something ||= something_else.
Re:Learn C The Hard Way by justincormack on Sunday July 03, 2011 @05:30AM (#2723408)
This type of code used to run faster when compilers did less. It makes no difference now. I think that is why it has stuck around. I prefer to write C that uses array references where it makes things clearer.
Re:Learn C The Hard Way by gregjor on Sunday July 03, 2011 @05:50AM (#2723431)
Don't think so. Kernighan et al. are the first to say code should be clear first and made fast only if it matters. This is clear code. It may (or may not) be faster than an array-based version but that's not the point of the exercise in K&R -- the point is to teach how pointers work.
Re:Learn C The Hard Way by nitrogen on Sunday July 03, 2011 @06:59AM (#2723482)
You'd be surprised what the compiler still doesn't do. For example, when writing a toy high-performance memory allocator for a university class, I was able to gain a significant[1] performance boost by replacing __attribute__((packed)) structs with pointer arithmetic #defines for the allocation block descriptors, with an identical memory layout.

[1] I don't remember the exact gain, but it was at least 10%.

Re:Learn C The Hard Way by daxelrod on Sunday July 03, 2011 @02:09AM (#2723207)
For me, the indirection of pointers was one of the fundamental CS concepts that required real effort to understand.

Before that point, I had never clearly separated the concept of a variable and its value. It took a huge conceptual leap to think about a variable that didn't hold a value, but rather, the location of a value. It took some serious mental gymnastics to deal with pointers n-levels deep.

Mind you, this was actually Perl references, not pointers, so I didn't even have to try to comprehend doing math on them.

After a while, of course, it became second nature.

My favorite aspect of CS is that every so often, I run into a wall of conceptual understanding that requires completely changing how I think in order to move forward. Have you never had moments like this, or were they just different topics?

Re:Learn C The Hard Way by ramidarigaz on Sunday July 03, 2011 @02:50AM (#2723240)
Actually learning about the stack was one of my big 'aha!' moments. I sorta' knew it existed, but I didn't really comprehend it.
Re:Learn C The Hard Way by adestefan on Sunday July 03, 2011 @10:13AM (#2723720)
Mainly because variable declarations are "backwards" in C. People try to read code left to right, but C declarations should be read right to left. Pile one things like the dual use of the static keyword, typedefs, and having multiple consts in a declaration figuring out the type of a variable can be a real chore. Dan Saks has a great article that hits on just the issues with const. http://dansaks.com/articles/1998-06%20Placing%20const%20in%2...
Re:Learn C The Hard Way by sp332 on Sunday July 03, 2011 @05:52PM (#2724705)
Or the classic "clockwise spiral rule" http://c-faq.com/decl/spiral.anderson.html :)
Re:Learn C The Hard Way by Goladus on Sunday July 03, 2011 @10:05AM (#2723706)
I can't speak for your friends, but while I had zero problems with pointers conceptually, I still had trouble using them in C. The problem wasn't the simple case of declaring a pointer and taking its reference, the difficulty came when the programs got complex and required agreement between function declarations, actual parameters in calls, and use within the functions.
Re:Learn C The Hard Way by nhebb on Sunday July 03, 2011 @12:21AM (#2723068)
> Do people really think C is some mysterious, inscrutable language?

Yes, I do. But it's not because of the language itself. It's trying to figure out what you can do with it after you grasp the fundamentals. I taught myself C using K&R a long time ago, but I never did anything with it. At the time I figured there were two paths I could progress along - UI related (e.g., a Windows app) or systems related (something Unixy). Both paths presented large hurdles. Nothing insurmountable, but I wasn't a programmer at the time - just doing it for my own edification. I always thought it would be nice if there was a second level book that took you from post-basics to writing something useful.

Re:Learn C The Hard Way by rpearl on Sunday July 03, 2011 @12:43AM (#2723092)
That's nothing to do with C as a language, but rather to do with relevant APIs, which can be difficult to read at times.
Re:Learn C The Hard Way by roundsquare on Saturday July 02, 2011 @10:50PM (#2722924)
It was for a while with me. I was a more "mathy" CS major which meant that languages that exposed what the computer was doing were more opaque to me... but I'm not sure that I ever considered it "scary and evil."
Re:Learn C The Hard Way by wvoq on Sunday July 03, 2011 @02:06AM (#2723204)
I don't intend to argue so much as to offer a data point: I suspect that most folks on this site learned C or something C-like early on, and have internalized its modus operandi. I have been learning C recently from a background of functional programming, and I find it scary and evil.

FWIW, I enjoy programming very much, and have built some non-trivial stuff in several languages. Still, I found C extremely taxing. Not in the sense that I felt it was beyond me, but in that I was fighting or recoiling from the language at practically every turn. In what follows, I am acutely aware that I am nowhere near fully fluent in C yet, and am writing only to offer the first impressions of a student. Nevertheless, in that time I have been able to draw on the advice of several "experienced colleagues", as K&R urge. In that sense, if I misstate the facts, I will be repeating the misconceptions of people who have objectively spent an awful lot of time writing C. I would be glad to be corrected on any point, but I'd also find that kind of symptomatic of the issues I have with C.

Firstly, C is incredibly stateful. I would be glad to learn that I am just Doing It Wrong, but there seem to be no obvious way around stateful manipulations as a way of life. Take, for instance, the fact that arrays are essentially second-class citizens and must be stuffed into functions as (pointers to) extra parameters in order to capture the "function's" "output". I am breaking out the scare quotes here since it is an abuse of vocabulary to refer to a procedure that communicates with the world by modifying its inputs as a function. If you have not cut your teeth on it, it seems almost obscurantist. If I want to multiply A by x and store the result in b, I want to write

b = matrixProduct(A,x);

not

matrixProduct(b, A, x);

as I must in C. I go back and forth over whether this is a deliberate and worthwhile performance tradeoff or just myopic design[1], but I don't want to have to settle for this in code I read every day.

There is also a kind of bureaucratic spirit in much C code, resulting from the fact that one must attend so closely to the how of computation rather than the what. In some contexts, like when you're doing distributed simulations that may run for days and performance is at an absolute premium, this emphasis may be appropriate. In most contexts, however, one finds oneself implementing and reimplementing standard operations by hand. Why should it take four lines to sum an array?

One of the most alarming symptoms of this style can be witnessed by watching an experienced C programmer read code. Old hands don't read lines, they scan an entire section of a page at a time. I was awed by this ability until I realized that it is possible only because each line of C does so little. I recall someone (probably in an HN comment) describing the "rhythm" of reading C code. That, to me, is not an encouraging sign.

Then there is, of course, the penance of debugging segfaults and space leaks. What happens when you declare 10 pointers and allocate 9 of them? No one knows, because C doesn't know either. It's up to the compiler. Towers of Hanoi, nasal demons, &c. Even with the help of with smart and experienced people, I've never spent so much time diagnosing such trivial, silent runtime errors. Yes, I know it's that way for a reason, but that reason is not legibility or ease of understanding.

At end, C has performance and a relatively (but not exceptionally) compact semantics. The importance of cycle-squeezing is becoming less of a consideration daily, for reasons well-rehearsed on this site and elsewhere. As for C's semantics, I'd much rather spend my time thinking about the transformations I want to map over my data than orchestrating von Neumann machines to carry those transformations out. If your model of computation is something other than register machines, it's not quite cricket to describe the implementation as magic.

-----------------------------

[1]I'd like to qualify that remark in two ways. Firstly, I certainly recognize the brilliance of K&R for working C from the raw conceptual materials of the time. Secondly language designers in 1969 did not have the benefit of the last 40 years' of object lessons in readability. There are many potential languages--points in language space, if you will--that are semantically identical or near-identical but much more readable than the ansi standard. For an example given by Kernighan himself, postfixing the dereference operator would have done miracles for legibility. Ultimately, a lot of more or less arbitrary choices were made early on and now it's too late to correct them.

Re:Learn C The Hard Way by s_tec on Monday July 04, 2011 @03:29AM (#2725708)
C is not the best way to manipulate information, as you have noticed. It's abstractions are all wrong. On the other hand, C is great for computer engineering, as opposed to computer science.

If you are writing firmware, for example, the exact sequence of memory writes is critical. Program the hardware registers in the wrong order, and the device doesn't work. Access the FIFO the wrong way, and your ISR has a data race. Hiding memory access from the programmer is useless when accessing memory correctly is the problem. C is pretty much the only usable language for this kind of work.

The guys writing kernels and system-level libraries face similar issues.

So, C is stateful because the hardware is stateful. C has raw pointers because the hardware has raw pointers. C doesn't manage memory for you because you don't want C to manage memory for you. This all makes sense when you realize that C was invented for writing operating systems.

So, while I do understand your criticism, I think you are looking at this from the wrong angle. The electrical engineering guys build the hardware, and the C guys make the hardware boot up. Fancy functional programming languages are useless without real machines to run on, and C makes those machines go. It's part of the plumbing, just like transistors. Plumbing may be messy and unpleasant, but even the architects designing skyscrapers need to know how it works.

Re:Learn C The Hard Way by wvoq on Tuesday July 05, 2011 @05:34PM (#2731688)
I fully acknowledge that there are domains where C is the best/only tool for the job. I was specifically taking issue with the claim that C is lucid, and neither scary nor evil.
Re:Learn C The Hard Way by s_tec on Tuesday July 05, 2011 @06:04PM (#2731789)
C is only opaque, scary, and evil if you consider computer hardware itself to be opaque, scary, and evil. For someone like an electrical engineer, C is perfectly lucid, safe, and friendly.
Re:Learn C The Hard Way by jwhite on Monday July 04, 2011 @08:32AM (#2726332)
Late to that party, but I'll give my $0.02 regardless.

I won't defend C: it's all that you say. I think one of the acknowledged reasons for C's longevity is that it is impedance-matched for UNIX because they grew up together, and for various reasons UNIX is popular with hackers; therefore C is popular. C is deeply rooted within UNIX, partly because the ABI has been so stable for so long. If you want to write a library for UNIX, you generally target C because anything else will run into a quagmire of cross-compiler incompatibility issues. That means all the good libraries on UNIX are written in C or present a C ABI/API. The easiest language to use a C library from is... C. Or C++. So application writers (and tool writers) have often favoured C as well, although the rise of interpreted languages such as Python, Perl, and Ruby has changed that a bit. Also, the C/C++ toolchains have tended to be more advanced than those of other languages.

So, C is still with us, but for reasons that don't have as much to do with its merits as a language as with its merits as a platform (when coupled with UNIX).

Re:Learn C The Hard Way by burgerbrain on Sunday July 03, 2011 @03:34AM (#2723286)
If you're thinking of arrays as second class citizens, you're thinking of the language incorrectly. Rather you should realize there are no arrays, only pointers to chunks of memory and arithmetic operations.
Re:Learn C The Hard Way by Goladus on Monday July 04, 2011 @08:47AM (#2726382)
There are arrays. C defines types. When you declare a variable as an array of int, C knows that variable is of type "array of int" and treats that differently than if it had been declared as "array of pointers to int" or "array of char" or "pointer to array of pointers to pointers to int".

I spent many years believing it when people made exactly the assertion you have(see my other posts on this article), but it wasn't until I tried to build a C compiler myself how wrong it is to think of arrays this way. Yes, C gives you the power to reference memory in a more or less arbitrary way. That does not mean that the arrays you declare are not arrays.

Re:Learn C The Hard Way by zvrba on Monday July 04, 2011 @04:33AM (#2725838)
You're wrong; there ARE arrays: make int a[16], *aa; and compare sizeof(a) with sizeof(aa). The confusion arises from the fact that the VALUE of an array is a pointer to its first element. When you consider that C is a pure pass-by-value language, everything fits nicely into place.
Re:Learn C The Hard Way by burgerbrain on Monday July 04, 2011 @04:36AM (#2725844)
sizeof behavior is just icing over what is really going on. You might as well argue that arrays really exist because we have the [] operator.
Re:Learn C The Hard Way by Goladus on Monday July 04, 2011 @08:59AM (#2726412)
No not really. What's really going on is that A has been declared as an array of 16 ints, while aa has been declared as a pointer to int. Those are different types, and C treats them differently sometimes (but not all times).
Re:Learn C The Hard Way by burgerbrain on Monday July 04, 2011 @12:49PM (#2727004)
Aside from the additional information that the C compiler is capable of knowing about in the case of A, it is the same crap going on under the hood.
Re:Learn C The Hard Way by Goladus on Tuesday July 05, 2011 @09:12AM (#2729667)
You're not writing in under-the-hood, though, you are writing in C. If you want to properly understand compiler warnings and errors you need to know that arrays and pointers are separate types.

Yes, "under the hood" it might be the same, but that's true of many languages if you dig deep enough. C is just a little closer. Yes, at one level a char declaration is just a smaller minimum memory allocation than int, but C will check both those types and if you want to use C properly you'll want to understand its typing and casting rules.

Re:Learn C The Hard Way by wvoq on Sunday July 03, 2011 @05:53PM (#2724709)
Well, QED.
Re:Learn C The Hard Way by zvrba on Monday July 04, 2011 @05:03AM (#2725905)
Programming boils down to paying attention to details. C is an extremely small, simple, predictable and malleable [] language that makes you painfully aware of that fact. For me, it is a pleasure to read well-written C code, for example the NetBSD kernel. There's a lot to learn there about elegance and good design.

[] malleable in the sense of bottom-up programming and defining your own "vocabularies". When I develop in C (and C++) I usually solve the problems 75% bottom-up and 25% top-down. With bottom-up approach, it is easy to stay focused at the problem at hand and write mostly bug-free code. The "top-down" bits just put pieces of the puzzle together.

Re:Learn C The Hard Way by justincormack on Sunday July 03, 2011 @05:27AM (#2723403)
It is possible to program C with a functional mindset, but the syntax does get in the way. The function syntax does not distinguish between parameters that are modified but you can by convention, and use of structs to bundle stuff up. You can pass function pointers liberally. In the end though the number of use cases for C is smaller now, and you should be able to avoid it for large projects and only use it for small pieces.
Re:Learn C The Hard Way by spc476 on Sunday July 03, 2011 @10:16PM (#2725147)
Actually, C89 can distinguish between parameters that are modifiable and those that are not. The syntax leaves a bit to be desired ("const foo_t x", "foo_t const x" and "const foo_t *const x" all have different semantics) but it can be done.
Re:Learn C The Hard Way by udoprog on Sunday July 03, 2011 @12:10AM (#2723050)
I haven't perceived that people think C is significantly scary (or evil). There are however many compelling reasons not too choose C in the present RAD/Web/Cloud/Solution Business world.
Re:Learn C The Hard Way by protomyth on Saturday July 02, 2011 @11:29PM (#2723004)
Given how many people freak out about retain/release memory management in Objective-C, it seems that C, pointers, and manual memory management is gotta be a lot scarier.
Re:Learn C The Hard Way by neutronicus on Sunday July 03, 2011 @07:56PM (#2724917)
C's scheme is much easier for me than objective-C's, mainly because of autorelease.
Re:Learn C The Hard Way by tomrod on Sunday July 03, 2011 @09:40PM (#2725093)
I've programmed now for 5 years, and I find C hard. But then, I've mainly programmed in C# and Python.