Comment by adrian_b
14 hours ago
I agree that the C flexible integer sizes were still necessary at the time of its creation, when some important computers still had word sizes that were not powers of two.
Nonetheless, I started to use C for programming only in 1990, when I got access to the Microsoft C and Borland Turbo C compilers.
At that time, 36 years ago, the C flexible integer sizes were already obsolete.
Since that time until now, while using C on a great variety of computers, from servers and workstations to the smallest microcontrollers, I have seen plenty of portability problems created by the existence of the flexible integer sizes.
The only programs that had no portability problems were those that never used the flexible integer sizes, but only integers with a definite size, e.g. 8-bit, 16-bit, 32-bit or 64-bit.
While sizeof solves the problems of memory allocation or copying, it does not help in preventing unexpected integer overflows, because even the size of "char" may be unknown, and even if the size of "char" is known, writing code with multiple paths that would check or prevent overflow for different integer sizes is very cumbersome.
Flexible integer sizes would work well only on the old computers, where integer overflow generated a hardware exception, so installing an overflow handler would have been sufficient to make the C code work correctly regardless of the size of the native integers.
The fixed size int types int32_t and friends weren't introduced until C99. Microsoft held out until 2013 before it put <inttypes.h> into Visual Studio!
So there has been a really long time in C's evolution where we haven't had fixed size types which has been a super annoying mess of #ifdefs in portable code.
The variable size ints have allowed some super weird architectures though. I remember looking at the datasheet for the Motorola 56000 DSP and noting that the C compiler set char = short = int = 24 bits! That was because the hardware could not address anything smaller than 24 bits. I think long could be 48 bits.
The product is named Visual C++, that it happened to do C was always kind of a sideshow as far as I could tell. Aside from that, I seem to recall that VC++ had the WORD, DWORD, and eventually QWORD macros to specify unsigned 16, 32 and 64 bit types respectively.
And their names are so frustrating. We don't run 16 bit systems any more. Word is a word that means something and I don't care what a word was on the 8086. The only honest things the WORD macro could expand to are size_t and ssize_t. 64bit is not a quad word, it's just a word.
Prior to Visual C++ (the first version of which shipped for Windows 3.x), Microsoft sold a “Microsoft C/C++” as well as Microsoft QuickC:
- https://winworldpc.com/product/microsoft-c-c/5x
- https://winworldpc.com/product/quick-c/10-for-windows
I always just defined these types in a per-platform portability header myself.
I would agree if overflow on those types wasn't undefined behaviour, or unpredictable
Plus char could be signed or unsigned!
Per the C standard `sizeof(char)` is always 1, regardless of how many bits it has.
because it's the unit of addressable memory that C is concerned by with sizeof, otherwise its values still depend on CHAR_BIT
> At that time, 36 years ago, the C flexible integer sizes were already obsolete.
This is a highly ignorant comment. You're confusing the fact that you only had to work with a single target architecture with the whole concept of multiple processor architectures being somehow obsolete, as if there was a sudden law of nature that forced every single computer, being full blown HPC stuff or small microcontrollers used in embedded applications.
Take a look at arduino. They still have 16-bit models out there. Also noteworthy, it seems some DSPs also have ints larger than 32 bits.
The parent is completely right in the sense that for actually portable C code it was always better to use fixed-width integer types which were chosen for the problem to solve instead of target hardware capabilities.
For instance if your integer arithmetic needs to happen with 32 bit precision (no matter if the code runs on a 16- or 32-bit CPU), there is no scenario where using 'int' makes sense. Instead you'd use a fixed-width 32-bit integer type and accept that math operations are compiled into two instructions on a 16-bit CPU.
And OTH if you only require 16 bits integer width, there's not much point in picking a 32 bit integer type. Since two's-complement integer encoding has been standard since at least the 70s, the CPU can do narrow operations in the native register width. Any overflow/wraparound is still correct when only looking at the lowest 16-bits of the result.
If you wanted portability you would use either long or int_least32_t for your example. On a platform that doesn't have a 32-bit type (E.g. a 24-bit DSP) the C99 standard doesn't require that int32_t exists.
I don't see the problem if you end up with a type that is larger than what you asked for, because (assuming signed arithmetic) it was undefined to overflow anyway.
> And OTH if you only require 16 bits integer width, there's not much point in picking a 32 bit integer type.
Some common architectures like x86 can suffer from an issue called partial register stalls. So from a performance perspective choosing a 32 bit integer can be better.
1 reply →
> The parent is completely right in the sense that for actually portable C code it was always better to use fixed-width integer types which were chosen for the problem to solve instead of target hardware capabilities.
You're confusing things. It's one thing to claim that either they never used a feature or they even have a personal preference to do things one way or another.
Another entirely different thing is to proclaim a programming language designed to target any conceivable CPU architecture somehow no longer needs to support basic cpu arch traits such as word size.
As I pointed out,there are still processors being sold today that do not support 32-bit ints. If you expect C to be able to target these architectures, obviously this feature is still a critical feature.
Also, people who maintain yesterday's systems that require non-32bit ints still need to work on them.
Chesterton's fence is still relevant. Why are we pretending that it's ok to mindlessly proclaim a feature is not requires because we don't understand why it was necessary to begin with?
1 reply →
As I have said, I have not worked with a single architecture.
Before 1990, I had worked with a variety of ISAs, from IBM mainframes and DEC minicomputers to many kinds of microprocessors.
After 1990, I have used C on a great variety of x86, Motorola 68xxx, IBM/Motorola PowerPC and many generations of ARM ISAs.
Even if you use explicit 32-bit integers in a program, that will not create any correctness problem when the program is run on 16-bit microcontroller. At most such a program may have a suboptimal performance. Performance problems are much easier solved during porting than obscure bugs.
There have been some popular DSPs with 24-bit integers, e.g. Motorola 56xxx. Nonetheless, nobody would want to run on such a DSP a program that was written for another kind of CPU, even for another kind of DSP, because the performance would be pathetic. Any program for such a fixed-point DSP, even when derived from an existing program, would need to be rewritten while using at every point in the program the knowledge that the size of "int" is 24 bits (because the programs for fixed-point DSPs need copious amounts of scaling operations, to avoid overflows and underflows), so such a program should not actually use "int", but it should typedef an "int24_t", to make this assumption explicit.