C file I/O (and C in general) is organized around bytes1 not bits. So there's generally no way to access specific bits in a file, just bytes.
So if you want to manipulate bits within a file, you need to read the bytes that contain the bits you are interested in and then extract the bits (generally using shifts and masks). If you want to write those bits back, you'll need to repack them into entire bytes.
One way is to have a bit stream abstraction layered on top of a C FILE * that can extract the bits from each byte read (keeping the remaining bits for a later read). Something like:
#include <stdio.h>
#include <limits.h>
struct bit_stream {
FILE *fp; // source to read from
int byte; // last byte read from fp
size_t bits; // how many bits are left in byte;
};
int read_bits(struct bit_stream *bs, size_t size) {
if (size >= sizeof(int)*CHAR_BIT) {
fprintf("size %z is too big\n", size);
exit(1); }
int rv = 0;
size_t bits = 0;
while (bits < size) {
if (!bs->bits) {
if ((bs->byte = fgetc(bs->fp)) == EOF)
return bits ? rv : EOF;
bs->bits = CHAR_BIT; }
if (bs->bits > size - bits) {
size_t extract = size - bits;
rv |= (bs->byte & ((1U << extract) - 1)) << bits;
bs->bits -= extract;
bs->byte >>= extract;
bits += extract;
} else {
rv |= bs->byte << bits;
bits += bs->bits;
bs->bits = 0; }
}
return rv;
}
int main() {
struct bit_stream bs = { stdin, 0, 0 };
int v;
while ((v = read_bits(&bs, 3) != EOF) {
printf("%d\n", v);
}
}
This uses read_bits(&bs, 3) to read the next 3 bits from the file.
1Bytes are pretty much always 8 bits these days, but the C standard still allows for other sizes of bytes, as specified by CHAR_BIT from <limits.h>
0and1are used to express bits?staticvariables to keep track of the bit position etc. If the buffer does not have enough bits, replenish and realign from the file buffer, and if that has no bytes, read some more (or just one) from the file.abcand then saving?