Live data from Hacker News

The Descent to C (2013)

chiark.greenend.org.uk

1–10 of 96 posts

Re: The Descent to C (2013)

#3

Hey! The author wrote PuTTY! That was a very informative read. I feel like I am the exact target audience: I'm coming from a programing background steeped in C# and I'm learning C from the K&R book.

Never thought pointers could expire, but it makes sense.

Re: The Descent to C (2013)

#4
> (In fact, that's what array[i] means – the language defines it to be a synonym for *(array+i).)

To really drive home the primitiveness of C arrays, should probably also mention that, because addition is commutative, you could also write

     i[array]
and somewhat surprisingly, it will compile, and work, and it means "*(i + array)" which is equivalent to "*(array + i)"

But nobody really does that, because that would be kind of insane.

Re: The Descent to C (2013)

#5

> (In fact, that's what array[i] means – the language defines it to be a synonym for *(array+i).) To really drive home the primitiveness of C arrays, should probably also mention that, because addition is commutative, you could also write i[array] and somewhat surprisingly, it will compile, and work, and it means "*(i + array)" which is equivalent to "*(array + i)" But nobody really does that, because that would be k…

Once the point is home, you can drive it a little bit more by exploiting the fact that string literals can be converted to pointers to the first characters, and do

    putc(2["ABCDEF"], stdout);
This prints 'C'.

Re: The Descent to C (2013)

#6

Hey! The author wrote PuTTY! That was a very informative read. I feel like I am the exact target audience: I'm coming from a programing background steeped in C# and I'm learning C from the K&R book.

There is also the excellent “Modern C” book:

https://modernc.gforge.inria.fr

The page has a link to a free PDF version.

Re: The Descent to C (2013)

#7
> No object orientation

I feel like C exists at a level below such concepts. Simply being able to define a function `void do_stuff(struct mystruct *obj)` opens the door to object-oriented style programming. A lot of people seem to define OOP by the presence of superficial stuff like inheritance, polymorphism etc, but really those are additional concepts that aren't useful for every program. The real difference is mutating state on the heap. So you could say C is an object-oriented language, by default, because it doesn't stop you doing this stuff, unlike a higher-level language like Clojure which simply doesn't have mutation (for the most part). Or you could say C is a functional language because if you don't explicitly pass pointers then you get copies. Really it's both and it's neither. It's whatever you want it to be.

Re: The Descent to C (2013)

#8
Some nitpicks with the article:

1. Much of section 2 is wrong except the part about arrays representing contiguous objects. The rest is largely an implementation detail.

Zeta C and Vacietis work considerably differently, as allowed by the standard

In addition there are many (mostly obsolete now) architectures in which, when you convert a pointer to an integer, you can't perform arithmetic and convert back because a pointer isn't just an integer address; it could represent segments or support hardware tags.

> C will typically let you just construct any pointer value you like by casting an integer to a pointer type, or by taking an existing pointer to one type and casting it so that it becomes a pointer to an entirely different type.

To be fair, they do say "typically" in here, but these behaviors are (depending on the case) all either implementation defined or undefined; the C standard specifies a union as the only well-defined way to type-pun to non character types.

> The undefined-behaviour problem with integer overflow wouldn't happen in machine code; that's a consequence of C needing to run fast on lots of very different kinds of computer, which is a problem machine code doesn't even try to solve

Some architectures trap on integer overflow, which I suspect is the reason why integer overflow is undefined rather than implementation defined. Certainly compilers today take advantage of the fact that it is undefined to make certain useful optimizations, but from what I can tell of the history that's not why it was undefined in the first place.

Re: The Descent to C (2013)

#9

> No object orientation I feel like C exists at a level below such concepts. Simply being able to define a function `void do_stuff(struct mystruct *obj)` opens the door to object-oriented style programming. A lot of people seem to define OOP by the presence of superficial stuff like inheritance, polymorphism etc, but really those are additional concepts that aren't useful for every program. The real difference is mut…

That you can do functional or OOP in C does not make C either kind of language, it just means that C is flexible enough that you can make the computer do things the way you want it to, no matter what that means, and other languages purposefully prevent you from doing what you might want to do.

C++ is object oriented not because it has compile time support for polymorphism or any of that other bad programming practice, but because classes have code sections that live with them, whether on the stack or in the heap, that can operate only on memory belonging to that instance of the class.

Object oriented programming is a coding style and choice. Some languages make it a first class part of the language design. It is purposefully not part of C.

However you can do OOP like things in C: a popular paradigm is to pass around pointers to structs that (should) live in the heap, and to have a number of functions which work on these structs. This is very similar in practice and mental modelling to OOP as users of C++ might know it, but is distinct in that no code ever lives in the stack or heap, and no code is restricted from operating on any of the program memory.

Re: The Descent to C (2013)

#10

> (In fact, that's what array[i] means – the language defines it to be a synonym for *(array+i).) To really drive home the primitiveness of C arrays, should probably also mention that, because addition is commutative, you could also write i[array] and somewhat surprisingly, it will compile, and work, and it means "*(i + array)" which is equivalent to "*(array + i)" But nobody really does that, because that would be k…

> nobody really does that, because that would be kind of insane

Yeah. That's why people don't do things in C. It's more like most C programmers probably weren't aware of this. After your comment, we'll start to see C codebases everywhere with that.

Post reply on HN