The answer is hardware design. Most machines are at best "Byte Addressable"
which means you have an address for a specific byte. In some cases, even if
the system is "Byte Addressable" it's still actually faster to use blocks
of bytes (2Byte/16bt, 4Byte/32bit, 8Byte/64bit). The reason why this is
true is because the hardware design was optimized to handle blocks. Though
I'm sure "Bit Addressable" hardware exists, I've never actually seen a
system like that.
EDIT: You're moving stuff into and out of registers (typically blocks
of specific sizes), but the registers are also not bit-addressable, hence
the need for bit-wise manipulation.
yes, but we don't care. A language is agnostic of the underlying system. Even the C standard is built on top of a machine that doesn't really exist.
Anyhow, the point is, limitations of the underlying system aren't excuses for why this syntax isn't implemented. If I can write bitmasks, then so can a compiler, right?
There are tons of useful features that aren't supported in C. The basic feature set of C was determined by whatever operations Dennis Ritchie could easily implement on the PDP-11 when he created the earliest C compilers. (Fun fact: the bitwise operators even preceded the Boolean operators like && and ||.)
If the question is "why isn't bit indexing supported" then "because processors didn't (and don't) support it" is the historically correct answer, whether you like it or not.
http://en.wikipedia.org/wiki/Bit_field -- BE WARNED. C bitfields might give you access to bits, but they're still aligned to the boundary of your system (DWORD boundary on x86 for example)
e.g.:
struct a {
unsigned a: 13;
unsigned b: 12;
};
sizeof(struct a) => 4;
in gcc they've got a flag to force structs to their actual bit size:
That's why C has bit fields. It effectively lets you access individual (or clumps) of bits as elements of a struct.
Now while this may not be as "convenient" as array-style indexing, it definitely is orders of magnitude better than using bit masks and what not. You could also argue forcing to name each clump of bits (as a bit field struct forces you to) is a good thing, because most of the time the use case calls for something like this, and simply numerically indexing into bits might not be the most readable approach.
EDIT: You're moving stuff into and out of registers (typically blocks of specific sizes), but the registers are also not bit-addressable, hence the need for bit-wise manipulation.