This is an interesting topic. It is about layers of software, abstract (computational) thinking, separation of concerns.
General programmers should not think about bits. They should only think in computational abstractions like those presented by a class as an algebra (set of values, operations on those values, and axioms about the values and operations). Programming should not be done thinking about bits, bytes, or words. That is BCPL, which C is based on, which makes C a mish-mash of programming, with poor separation of concerns.
Of course, programmers might disparage languages with separation of concerns that “I wanted to do … and I couldn’t”. That does not make a language weak, in fact it makes it strong, because abstractions are not undermined. Management likes to choose things using a check list — the more ticks the better. Bit-level operations… tick, must be good. But the absence of the tick is the right option. Trying to change this thinking in the programming profession is difficult.
Mixing in thinking about bits undermines abstractions. This makes for unsafe and insecure programming. (Unsafe versus insecure was addressed by Vint Cerf in a recent CACM.)
In the OSI stack, bit manipulation of data formats is done at the presentation level saving anything written at the application level having to deal with that. System programming is about dealing with the details (non abstract) so that others don’t have to. Class encapsulation is about dealing with the details of a type so that others don’t have to or lock their software into those details.
Undoubtedly for the presentation layer, bit operations are required. But mixing them in an application- and problem-oriented language is a disaster leading programmers to use those operations, resulting in inflexible software and lock in (which C and C++ achieve admirably for the wrong reasons).
So how do we satisfy both needs?
We could just throw everything in as C and C++ do. Obviously I think that is a poor, cheap-and-nasty solution. But it feeds programmers who have been taught about bits, bytes, and words instead of abstract, computational thinking. Of course part of a CS course must teach how it works underneath, but students then miss the important learning about abstract thinking.
We could extend a language with ‘dangerous’ low-level operations, flagged as such. This seems to be the Rust approach, which is rather like Burroughs/Unisys NEWP (which annotates blocks with many levels of different dangerous facilities much more fine-grained than Rust).
See section 8 ‘Unsafe Mode’.
However, NEWP is only the language for the MCP OS, no programs are written in it (except some low-level stand-alone utilities). The ALGOL-based languages are also layered, with NEWP for the OS, DCALGOL for middleware and presentation layer, and Extended ALGOL for general systems programming (with events and interrupts if required). Application languages are on top of that.
Eiffel has CECIL (is that up-to-date?) to call to languages that do bit-level when needed. This ensures separation of concerns.
A class could be written to encapsulate bit-level operations. I think making such operations generally available would be a mistake.