Tricky stuff

Here, I collect a few annoying pitfalls of the language.

Grammar

So 071 is 57?

The leading 0 means it's an octal number, so 071 = 7×8+1 = 57, not 71. This "feature" is annoying: who uses octal numbers these days? If you want a prefix for octal numbers, make it 'o' instead of '0').

Pointers, array and sizeof

sizeof(array/pointer), part 1

In a 32-bit machine, with a declaration int a[3], *p;
you get,
sizeof(a) = 3×4=12;
but
sizeof(p) = 4 = sizeof a pointer.

sizeof(array/pointer), part 2

2D arrays/pointers are even trickier:
with int a[3][3], (*p)[3], **q;
you get,
sizeof(a) = 3×3×sizeof(int); = 36;
sizeof(*p) = 3×sizeof(int) = 12;
sizeof(*q) = 4 = sizeof(void *);

pointer function parameter

The function parameter is always a pointer, even if you declare it as an array, e.g., size_t f(int a[10]) { return sizeof(a); } yields the size of a pointer = 4, instead of 10×sizeof(int) = 40.
However
size_t f(int (*pa)[10]) { return sizeof(*pa); } will give 10×sizeof(int) = 40.

Example code for the above three points.

The standard library

fgetc() returns int

getchar(), fgetc() returns an int instead of char, because −1 means EOF, 0-127 means normal ASCII, 128-255 means non-ASCII code.
So if it's not −1, we could convert the output as (char)(unsigned char)c.

ungetc() only works once

The standard only guarantees that the first ungetc() works, calling it succesively may or may not work.

Alternative 1: implement a buffer yourself.

Alternative 2: use fgetpos() and fsetpos() to save and restore a position.

strncpy()

strncpy(s, t, 5); copies five characters from string t, but s is not necessarily terminated with a '\0' if string t is too long. So you should do it manually after the function call like
s[5] = '\0';
and make sure that the string s can contain at least 6 instead 5 characters.

A more elegant solution is:
sprintf(s, "%.5s", t);

strcmp(s, t)

strcmp() returns 0 if s is equal to t. It may be natural to write
if (strcmp(s, t)) ...
but it should be
if (strcmp(s, t) == 0) ...

gets() unsafe

Always use fgets(s, sizeof s, fp) instead, even if fp is stdin.

†GNU programmers sometimes argue that fgets() is also unsafe, if the file is binary and contains a '\0'. But I usually assume a good text file, so fgets() works.

printf() and scanf()

See the printf() page.