AT&T's 1984 official The C Programming Handbook recognizes one compiler with 9-bit chars.
Plus another compiler in EBCDIC!
Simply put, there is nothing inherent in C that would require word size to be a power of 2. The reason we expect it today is because all modern systems do so, in turn related to computing history.
In one word: packaging.
Summary
- There is no absolute reason why word size has to be a power of 2.
- For mainframe/minicomputers, the size of an IC package is irrelevant. The computers are built from individual low-level logic chips, so they could (and often did) have strange word sizes.
- The first microprocessor was 4 bits because of packaging constraints.
- For several reasons, microprocessor word size has grown by doubling. Thus, microprocessor word sizes have become powers of 2.
- Microprocessor speed was severely limited by packaging limitations, until they started using larger non-DIP packages. Then microprocessor speed surpassed mainframe/minicomputers, leading to the demise of the latter.
- Because nearly every computer today is built from microprocessors, we mistakenly assume that word size always must be a power of 2.
(1) No C requirement for a power of 2.
This manual was written in 1984 by AT&T Bell Labs to train programmers to write in C. It was published in the time between the 1st and 2nd editions of Kernighan and Ritchie.
.
Compilers have been written for at least one platform with a non-power-of-2 word size. Examine the entry for the Honeywell 6000:
.
Also note that C doesn't have to be in ASCII; the entry for the IBM 360/370 shows EBCDIC.
The 2nd edition of K&R reinforces this point:
Each compiler is free to choose appropriate sizes for its own hardware, subject only to the restriction that short
s and int
s are at least 16 bits, long
s are at least 32 bits, and short
is no longer than int
, which is no longer than long
.
Kernighan and Ritchie, The C Programming Language, 2nd edition, 1988. p. 36
Do characters have to be individually addressable by hardware? No, there have been plenty of systems that load/store whole words and then let the compiler do the magic. On the Honeywell 6000, sometimes programmers would pack 5x 7-bit mixed-case ASCII, or 6x 6-bit upper-case ASCII, into one 36-bit word. This was especially popular in COBOL programs to save memory.
Do larger data sizes have to be a whole multiple of smaller data sizes? In theory, no. You could theoretically have 9 bit char, 15 bit short, and 33 bit longs. In practice, either the processor or the compiler has to deal with this weirdness, and it's not a trivial task. So in practice, every compiler ever made has simply made all data sizes a multiple of a char.
(2) Mainframes and minicomputers
Early computers were constructed from individual vacuum tubes, transistors, or small-scale integrated circuits (such as the 7400 and 74000 series). Those that filled an entire room were generally called mainframes, whereas minicomputers were typically the size of one equipment rack or smaller. The former usually had more memory, mass storage, and peripherals than the latter, hence the increased size and cost.
Designers of these systems picked a word size that was appropriate for their needs. Many systems had word sizes that weren't powers of 2. The GE 600 (and its successor the Honeywell 6000) had 36 bits. The PDP 8 had 12 bits. The Nicolet 1080 had 20 bits.
Because the processor is not confined to one chip, it didn't matter how many pins were on the ICs that were used. If one IC wasn't enough for your needs, you just wire up more. That's why these computers took up so much space and cost.
On the other hand, these computers could be quite fast. With full-sized address and data buses, they could load or store an entire word in just one clock cycle.
(3) The first microprocessor
Microprocessors consolidate all arithmetic, logic, and control functions on to one integrated circuit. The Intel 4004 is often cited as the first microprocessor.
Side notes: Some claim the MP944 as the first microprocessor, but it was a military design that was classified until 1998, so it had no impact on future processor design. Microcontrollers are one-chip solutions that also include ROM, RAM, and I/O on one chip; most of what I say about microprocessors also applies to microcontrollers.
The 4004 project was initiated by a customer who wanted to build a calculator. Intel quickly realized that the customer's design would require a 40-pin package, when Intel had manufacturing equipment only for 16-pin chips. Thus, the design was scaled back to using 4-bit words. Conveniently, 4 bits is just enough to support the binary-coded-decimal used in a calculator.
Although the 4004 is 4 bits wide externally, it uses 8-bit instructions and 12-bit addresses. This is accomplished by multiplexing the external bus for both address and data. Loading or storing data requires three cycles for the address and one cycle for the data; an instruction fetch uses three cycles for address and two for the instruction.
This "bus bottleneck" was a result of packaging limitations, made the 4004 much slower than a similarly-clocked minicomputer would be. It also required extra hardware outside the chip to decode and latch signals. These issues would continue for about another 25 years in further microprocessor architectures.
(4) Word sizes double
Four bits is simply not enough for most applications (especially not a calculator). However, one can create larger data types by operating on multiple words. For example, you can add two 8-bit numbers by combining the additions of two pairs of 4-bit numbers.
You could hypothetically use a similar process to add 12-bit numbers. (This was in fact used in the 12-bit Intersil 6100 used by the PDP-8.) However, as long as you have written the code to add two 8-bit numbers, why not re-use that code to add two 16-bit numbers? And then re-use that to add 32-bit numbers? You can see how this doubles the number of bits each time you increase the data size, leading to data sizes that are powers of 2.
Another issue with the 4004 was that the instruction size was two words (8 bits). Even later processor designs often required some multi-word instructions. If you double the bits of the external bus, it will take fewer cycles to fetch instructions.
Powers of 2 are also attractive to computer designers, as they are already familiar with them through other aspects of computing.
Thus, Intel's next processor (the 8008) had double the word size of the 4004: 8 bits. The package now had 18 pins, again creating a bus bottleneck. This was followed by the 8080, which had 40 pins, was much faster, and was easier to interface.
Other processors entered the market after the 8008. By then, the usefulness of word sizes that are powers of 2 had already been established, and processor designers eagerly accepted them.
(5) New packaging overcomes limits
Business users continued to purchase mainframes and minicomputers into the mid-1990s, as they were significantly faster than microprocessor-based machines. The reason was the bus bottleneck imposed by microprocessor packaging.
Until the 1990s, most processors were housed in dual inline packages (DIP). Most designs had 40 pins or less, although the Motorola MC68000 is an impressive exception at 64 pins. As the number of pins on a DIP grows, the package takes up a lot more board space, and the wires that connect the corner pins grow longer, which is a bad thing at high frequencies. Thus, microprocessor designers did their best to limit pin count, even if this meant reducing the size of external buses. This causes the bus bottleneck, previously described.
In contrast, mainframes and minicomputers use as many chips as they need to build the processor. Buses are the full width throughout the machine, so there is no bus bottleneck, making them faster than contemporary microprocessors.
During the 1990s, chipmakers began using other forms of packaging, such as quad flat packs, plastic leadless chip carriers, pin-grid arrays, and ball-grid arrays. These new forms allowed more than 40 pins, enabling larger external microprocessor buses.
Freed of the bus bottleneck, microprocessor instruction speeds increased dramatically. Of course, there were other factors in play. Tricks such as caching and pipelining were "borrowed" from mainframes. Reduced Instruction Set Computing (RISC) made one-cycle instruction fetches. Smaller transistor sizes and computer-aided chip design helped increase the number of transistors per chip, as well as boost clock speeds. Compilers became smarter. Regardless, microprocessors quickly outpaced the speed of mainframes and minicomputers.
(6) Computers today
Mainframes and minicomputers became obsolete by the end of the 1990s. Why bother making a system out of discrete chips when a microprocessor is cheaper, smaller, and faster? Of course, there are still room-sized computers -- but they are now server farms made of hundreds or thousands of microprocessors, not discrete chips.
Practically all computers today use microprocessors, which in turn have word sizes that are powers of 2. Thus, we often assume that a processor's word size has to be a power of 2. Although practical, it is not a requirement.
char
,short
,int
,long
, etc.) and thus "weird" word sizes may not have been an issue at all. But I don't know enough about early C to say for sure.stdint.h