O O Ø O O O O
C Programming Tidbits
Sometimes I have to rack my brain for the correct way to do something in C. This is a collection of tidbits that are, to the best of my knowledge, the right way to do things.
Links
Why C is not my Favourite Programming Language.
Portability
Good luck finding a consistent C standard that contains the functions you use. (Of course, C99 doesn't contain strdup. Why would it?). I have an ongoing project documenting portability goo as I encounter it.
Correct use
Some C functions are designed to be misused. Here are some of my least favorites:
- strncpy
-
Problem: it returns an int. It *should* return a size_t, or at worse, ssize_t (since it also returns a -1 on error). Proper use is likely something like:
char *buf[100], *bar; int n; ... n = snprintf(buf, sizeof(buf), "buffer: %s", bar); if (n < 0 || n >= sizeof(buf)) /* handle error */An explicit test against -1 (
if (n == -1 ...)) is probably also safe, since the only sane thing snprintf can do when asked to copy more than INT_MAX characters is to return an error.
Bitfields
Set / Clear bits
Assume we are using a 32-bit unsigned type called uint32. We can set or clear bit i using the following:
bits[i / 32] &= ~((uint32)1 << (i & 31)); bits[i / 32] |= (uint32)1 << (i & 31);
Note that the typecast on the 1 becomes very important when dealing with types longer than an int (i.e. long long). Most compilers will implicitly assume 1 is an int, so shifting it by 32 positions or more will not have the desired effect (where int == 32 bits).
Also note that the range on the shift operators appear to be (for an n-bit quantity) 0 ... n-1. The expression:
uint u32, i; i = 32; u32 = u32 << i;
appears to have no effect. The value in u32 is simply not shifted. (noted on a linux box with gcc 2.96).