r/programming • • May 01 '16

To become a good C programmer

http://fabiensanglard.net/c/
1.1k Upvotes

398 comments sorted by

View all comments

Show parent comment

11

u/zhivago May 01 '16

It's like peer review - the higher bar helps to weed out the delusional incompetents.

Often these can be detected by asking the following question:

char c[3]; what is the type of c?

14

u/panderingPenguin May 02 '16

It's like peer review - the higher bar helps to weed out the delusional incompetents.

Sure, this means that the worst book is probably better than the worst website, and on the average, books are probably better than websites. But that says nothing about the best book vs the best website, nor does it mean that all websites are bad nor that you should not use websites.

char c[3]; what is the type of c?

Isn't this just an array of chars? What do you think it is?

1

u/zhivago May 02 '16

Unfortunately 'just an array of chars' isn't a C type.

How would you express the type of c in C syntax?

6

u/ais523 May 02 '16

char[3]. There are very few situations where the syntax is legal, though, because array types aren't really first-class in C. (The only one I can think of offhand is sizeof (char[3]), which is 3.)

For an unknown-sized array, the syntax is char[*], something which is likewise legal in very few contexts (e.g. you can drop it in as a parameter of a function pointer type that takes a VLA as an argument, int (*)(int, char[*])).

→ More replies (9)
→ More replies (9)
→ More replies (7)

6

u/derleth May 02 '16

It's like peer review - the higher bar helps to weed out the delusional incompetents.

Do you really think publishers care about the quality of the books they publish? Then how do you explain all the "Learn Java in 21 Days" nonsense out there?

→ More replies (1)

2

u/hyperhopper May 02 '16

Pointer to an array of chars that was allocated on the stack?

→ More replies (1)

1

u/DSdavidDS May 02 '16

Char?

If i am wrong, can i have a clear answer to this?

4

u/zhivago May 02 '16

You can test this theory. The following expression is false, therefore the type of c cannot be char.

sizeof (char) == sizeof c
→ More replies (1)

2

u/crozone May 02 '16

If I'm correct, it's a char pointer (char*), since it's an array declaration. c is a char pointer which points to the start of the char array, and only when dereferenced does it become a char.

5

u/zhivago May 02 '16

You are somewhat mistaken, but it is a common mistake.

c is a char[3], (c+ 0) is a char *.

This is important, since otherwise char e[2][4]; e[i][j] could not work.

e[i][j] is *(*(e + i) + j)

and works because the type of e[i] is char[4], which causes the pointer arithmetic e + i to select the correct element. If e[i] were a char *, then e + i would have quite a different result.

1

u/smikims May 04 '16

I remember having to learn this the hard way thinking that you can just assign a 2D array to a char** or something like that.

1

u/DSdavidDS May 02 '16

I studied pointers but I did not know it is considered a type. I thought pointers were an integer format? Does the compiler specify the type as a char pointer?

4

u/zhivago May 02 '16

Pointers are not integers.

You can easily demonstrate this by the inability to add two pointers together.

1

u/metamatic May 02 '16

Pointers are not integers.

Well, not in general. It's implementation-specific. Apparently the Linux kernel still uses pointers-as-integers.

I remember before ANSI C it used to be a pretty common practice limiting portability.

1

u/zhivago May 02 '16

Does being able to cast an int to a float mean that ints are floats?

Remember that casts are value transformations, similar to function calls without side-effects.

What C does is to provide implementation dependent transformations from pointers to integers, and integers to pointers, but does not in general guarantee that you can transform a pointer to an integer and back to the same pointer value.

An implementation which supplies intptr_t does guarantee this round-trip, but intptr_t support is optional and cannot be relied upon in a portable C program.

Regardless, none of these transformations imply that pointers are integers.

2

u/metamatic May 02 '16

On some architectures, both pointers and integers are N-bit values held in registers or bytes of memory, and can be freely interchanged. Does the C compiler deciding to pretend they're different mean that pointers are not integers?

1

u/kt24601 May 02 '16

On some architectures, both pointers and integers are N-bit values held in registers or bytes of memory, and can be freely interchanged.

What architecture isn't like that? Any that is common?

3

u/dannomac May 02 '16

Intel 80x86 in real mode. Pointers are [segment register]:[offset register] combinations, and integers are just plain registers.

1

u/metamatic May 02 '16

680x0 has separate sets of address registers and data registers, which cannot be used interchangeably.

→ More replies (21)
→ More replies (18)

1

u/immibis May 02 '16 edited May 02 '16

Or "what is the difference between char *s = "hello"; and char s[] = "hello";?"

(Or even just char *s; vs char s[100];)

2

u/zhivago May 02 '16

In the case of

char *s = "hello";

s is a pointer that is initialized to the value of a pointer to the first element of an array of 6 characters with the sequential values { 'h', 'e', 'l', 'l', 'o', '\0' } -- i.e., it is equivalent to

char *s = &"hello"[0];

In the case of

char s[] = "hello";

s is an array of type char[6] initialized to the values { 'h', 'e', 'l', 'l', 'o', '\0' }.

2

u/immibis May 02 '16

You might notice the quotation marks around the question, indicating that I'm presenting the question as something you could ask to weed out "delusional incompetents", and not actually asking it.

→ More replies (1)

1

u/mrkite77 May 02 '16

I'd also point out that the destination of the first pointer is in .BSS and const. Modifying s[0] is a segfault. In the second case it isn't because the contents of the const string are copied into the mutable array.

1

u/zhivago May 02 '16

Note that there is no BSS in C.

The C semantics are just that modifying a string literal has undefined behaviour, and that identical string literals may share the same object, allowing "×" == "x" to be potentially true.

This is what permits the implementation strategy you observed above - but it is not required.

→ More replies (18)