Live data from Hacker News

Essential C (2003) [pdf]

cslibrary.stanford.edu

21–30 of 84 posts

Re: Essential C (2003) [pdf]

#21
post #18
post #9

This is a pretty neat guide if you’re cheap and have moral qualms about pirating K&R. Still, I think the best introduction to C remains K&R.

K&R is woefully out of date. Gives you no info on how to do things safely and sanely. And encourages a leet style of programming that results in catastrophic edge case bugs. As you can see in comments above where naive code that iterates backwards through an array fails when the array size is 0. Worse K&R leet style buys you absolutely nothing with a optimizing compiler written in the last 30 years.

K&R is actually fairly reasonable about performance, and much less l33t than code I have seen in the wild. It is a very good introduction about the language, and although I would not ever call it "woefully out of date" I would say that it is a good idea to read more about the current state of bugs and tooling, which is not discussed because the book is a general overview of the language.

Re: Essential C (2003) [pdf]

#22
This guide is short (which is always nice) but not has a couple of flaws in places in the brief skim I gave it. For example:

> In particular, if you are designing a function that will be implemented on several different machines, it is a good idea to use typedefs to set up types like Int32 for 32 bit int and Int16 for 16 bit int.

Use please

> The char constant 'A' is really just a synonym for the ordinary integer value 65 which is the ASCII value

Not always, especially right after you came off a paragraph explaining how different machines have implementation-specific behaviors

> The compiler can do whatever it wants in overflow situations -- typically the high order bits just vanish.

This is a good time to explain what undefined behavior actually means

> The // comment form is so handy that many C compilers now also support it, although it is not technically part of the C language.

Part of the language since C99

> C does not have a distinct boolean type

_Bool since C99

> Relying on the difference between the pre and post variations of these operators is a classic area of C programmer ego showmanship.

I'm fine with you mentioning that this can be tricky, but this is more opinion than I am comfortable with in an introductory text

> The value 0 is false, anything else is true. The operators evaluate left to right and stop as soon as the truth or falsity of the expression can be deduced. (Such operators are called "short circuiting") In ANSI C, these are furthermore guaranteed to use 1 to represent true, and not just some random non-zero bit pattern.

Under the assumption that there are no boolean types from earlier, this is not true

> The do-while is an unpopular area of the language, most everyone tries to use the straight while if at all possible.

I would argue that people use do-while more than they need to

> I generally stick the * on the left with the type.

Not a problem, but :(

> The & operator is one of the ways that pointers are set to point to things. The & operator computes a pointer to the argument to its right. The argument can be any variable which takes up space in the stack or heap

And constants/globals

> To avoid buffer overflow attacks, production code should check the size of the data first, to make sure it fits in the destination string. See the strlcpy() function in Appendix A.

strlcpy is non-standard and probably not what you want

> The programmer is allowed to cast any pointer type to any other pointer type like this to change the code the compiler generates.

> p = (int * ) ( ((char * )p) + 12); // [Some spaces added by me to prevent Hacker News from eating the formatting]

Only in some very specific cases…

> Because the block pointer returned by malloc() is a void* (i.e. it makes no claim about the type of its pointee), a cast will probably be required when storing the void* pointer into a regular typed pointer.

Casting malloc is never required (and I would say usually not a good thing to do)

Re: Essential C (2003) [pdf]

#23
post #13

Earlier quoted context omitted.

Yeah, so then you write for (size_t i = n-1; i It works fine (unsigned overflow is well defined) but it's even less clear.

It seems sensible to always just use signed values for indices. Indices are difference types, which should include negative values so that you can subtract two indices and get a sane delta. The range of signed values seems 'big enough.'

The C language "de facto" uses size_t for indexing and ptrdiff_t for differences, or the rare case where you have a negative index.

Re: Essential C (2003) [pdf]

#24
post #13

Earlier quoted context omitted.

It seems sensible to always just use signed values for indices. Indices are difference types, which should include negative values so that you can subtract two indices and get a sane delta. The range of signed values seems 'big enough.'

> Indices are difference types Umm, no? Indices are ordinals[0], forming the canonical/nominal well-ordering of a collection such as a array. > an ordinal number, or ordinal, is one generalization of the concept of a natural number that is used to describe a way to arrange a (possibly infinite) collection of objects in order, one after another. [...] Ordinal numbers are thus the "labels" needed to arrange collections…

In C an index is a difference that you add to a pointer to get a pointer. `a[i]` is `*(a + i)`. Given two indices `i` and `j`, you want `i - j` to be such that `a[j + (i - j)]` is `a[i]`, and it then makes sense to me that `i - j` is signed. The expression works out whether they are signed or unsigned, but just in terms of their interpretation on the part of a user (eg. "oh this is 2 elements before bc. it says -2") or so that comparisons like `i < j` are equivalent to `i - j < 0` and so on. That's why it's always made sense to me to use `ptrdiff_t` (or just `int`) for an index, vs. using `size_t`.

Re: Essential C (2003) [pdf]

#25

This guide is short (which is always nice) but not has a couple of flaws in places in the brief skim I gave it. For example: > In particular, if you are designing a function that will be implemented on several different machines, it is a good idea to use typedefs to set up types like Int32 for 32 bit int and Int16 for 16 bit int. Use please > The char constant 'A' is really just a synonym for the ordinary integer val…

> Under the assumption that there are no boolean types from earlier, this is not true

Can you elaborate on this one? I thought && and || expressions always evaluated to 0 or 1.

Re: Essential C (2003) [pdf]

#26

This guide is short (which is always nice) but not has a couple of flaws in places in the brief skim I gave it. For example: > In particular, if you are designing a function that will be implemented on several different machines, it is a good idea to use typedefs to set up types like Int32 for 32 bit int and Int16 for 16 bit int. Use please > The char constant 'A' is really just a synonym for the ordinary integer val…

>> The value 0 is false, anything else is true. The operators evaluate left to right and stop as soon as the truth or falsity of the expression can be deduced. (Such operators are called "short circuiting") In ANSI C, these are furthermore guaranteed to use 1 to represent true, and not just some random non-zero bit pattern.

> Under the assumption that there are no boolean types from earlier, this is not true

Actually, I believe _Bool is guaranteed to use 0 for false, and any non-0 value is stored as 1 for true. Arithmetic on _Bool is also guaranteed, based on those values.

For example, I believe the standard guarantees:

    _Bool x = 255;
    assert(x == 1);

    size_t y = 10 + x;
    assert(y == 11);

Re: Essential C (2003) [pdf]

#28

This guide is short (which is always nice) but not has a couple of flaws in places in the brief skim I gave it. For example: > In particular, if you are designing a function that will be implemented on several different machines, it is a good idea to use typedefs to set up types like Int32 for 32 bit int and Int16 for 16 bit int. Use please > The char constant 'A' is really just a synonym for the ordinary integer val…

> Under the assumption that there are no boolean types from earlier, this is not true Can you elaborate on this one? I thought && and || expressions always evaluated to 0 or 1.

Now that I think about it, I think that depends on what you mean by "use". I was commenting from a perspective that you can pass in something that is not 0 or 1, and in general it is not advised to assume that a "boolean" is 0 or 1 especially given that this document doesn't mention the boolean type (which is guaranteed to have those values). This is true even under ANSI C, because as it mentions later, programmers depend on any nonzero value being "truthy".

Re: Essential C (2003) [pdf]

#29
post #26

This guide is short (which is always nice) but not has a couple of flaws in places in the brief skim I gave it. For example: > In particular, if you are designing a function that will be implemented on several different machines, it is a good idea to use typedefs to set up types like Int32 for 32 bit int and Int16 for 16 bit int. Use please > The char constant 'A' is really just a synonym for the ordinary integer val…

>> The value 0 is false, anything else is true. The operators evaluate left to right and stop as soon as the truth or falsity of the expression can be deduced. (Such operators are called "short circuiting") In ANSI C, these are furthermore guaranteed to use 1 to represent true, and not just some random non-zero bit pattern. > Under the assumption that there are no boolean types from earlier, this is not true Actually…

This is exactly why I included earlier bit where they claimed there was no boolean type, to show that their conclusion is logically inconsistent rather than just incomplete ;)

Re: Essential C (2003) [pdf]

#30

I highly recommend the CS50 course to get familiar with C: https://www.youtube.com/playlist?list=PLhQjrBD2T381L3iZyDTxR... Sure it doesn't get in details about the language but you get the essential and the videos are great.

I'm doing CS50x at the moment and I can definitely recommend it. It got me interested in C despite trying to avoid it my entire life. David Malan is one of the best lecturers I've seen.
Post reply on HN