Does anyone know of any platforms supported by the C standard, for which there is still active development work, but which are:
About a decade ago we had to port our C embedded database to a DSP processor that happened to be the main processor of a car stereo. It was a 24-bit machine, in the worst way: sizeof(char) == sizeof(int) == sizeof(void*) == 1
, which was 24 bits. We named the branch that dealt with this port "24-bit hell".
Since then we ported our library to many platforms, but none as weird as that. They may still be out there (cheap 24-bit DSP chips are even cheaper now), found in low-cost devices where ease of programming is a distant second to a low bill of materials (BOM). Come to think of it, I think we did encounter a machine where a right shift of an unsigned integer did not necessarily insert zero bits. Even so, highly nonstandard arithmetic rules on a platform guarantee challenging, error-prone porting of software to it, which dramatically increases software development costs. At some point sanity prevails and standards are observed.
I suspect that a lot of the motivation for the presence of these rules in C99 is their presence in C89, and earlier iterations of the language. Don't forget that when C was invented, computers were a lot more diverse than they are today. "Bit-slice" processor designs were available where you could add as many bits as you wanted to your processor just by adding chips. And before C you had to code in assembly language or worry about exactly where in RAM your code would reside, etc.
C was a dramatic step forward in terms of portability, but it had to corral a diverse range of systems, hence the very general rules. 20 years later, when Java came around, it had the benefit of history to allow it to declare up-front how big primitive types were to be, which makes everything a lot easier, as long as Java's choices are sound.
I know you are mostly asking about integers, but I have encountered some weirdness when it comes to pointers. Early Macintosh computers had 32-bit processors (Motorola 68000), but only 24-bit memory busses. Thus 0x00123456 and 0xFF123456 referred to the same memory cell, because the processor chopped off the upper 8 bits when accessing RAM. Apple engineers used these bits to store metadata about the memory that the pointer pointed to. Thus when comparing pointers, one had to mask off the upper bits first. And don't get me started on the segmented memory architectures of the x86. :)
Since we are on this topic, take a look at the MISRA coding standard, which is favored by makers of automobiles that need maximum portability and safety. Also look at Hacker's Delight by Henry S. Warren, which has tons of useful bit twiddling tricks in it.
The cc65 compiler for Commodore C64 seem to have had some update as late as last year.
My two cents. Please don't blame hard, this is from my experience, I'm not a theoretic:
All of the existing CPU's are 2's complement
There are 8 and 16 bits architectures too. 8 bit AVR MCU's is a good example.
I am not aware of any system, that pads integers. Floating numbers - is a different story.
All of the above - not aware of any, and I assume there is no such machine.
An old adage (I forgot the attribution) says that
there is no such thing as portable code
But only that there are some code which have been ported.
You should not care about writing portable code, you should care about writing code that will be easy to port to other platforms.
Besides, using only the C standard gives you not many useful things. Posix standards gives you much more.
Even if these machines are ancient, there's still an active community programming for PDP-8, most but not all using simulations: PDP-8 as an example. And this machine, AFAIK, uses 12-bit integers!
I recently worked at a company which still used a version of the PDP-10, and a port of GCC to that platform. The 10 we used had a few of the attributes you list:
In addition to the above unusual attributes, there was the issue that the machine had several different byte addressing mechanisms. Bytes with widths in the range of 6-12 bits wide could be addressed by using special bits in the address itself which indicated which width and word alignment was being used. To represent a char* one could use a representation which would address 8-bit bytes, all of which were left-aligned in the word, leaving 4-bits in each 36-bit word which were not addressed at all. Alternatively 9-bit bytes could be used which would fit evenly into the 36-bit word. Both such approaches had there pitfalls for portability, but at the time I left it was deemed more practical to use the 8-bit bytes because of interaction with TCP/IP networking and standard devices which often think in terms of 16, 24, or 32-bit fields which also have an underlying structure of 8-bit bytes.
As far as I know this platform is still being used in products in the field, and there is a compiler developer at this company keeping relatively recent versions of GCC up to date in order to allow for further C development on this platform.