> floating-point number types will not be discussed at all, because that mostly deals with how to analyze and handle approximation errors that stem from rounding. By contrast, integer math is a foundation of programming and computer science, and all calculations are always exact in theory (ignoring implementations issues like overflow).
Integer overflow is no mere implementation issue, any more than errors are an implementation issue with floating-point.
> Unqualified char may be signed or unsigned, which is implementation-defined.
> Unqualified short, int, long, and long long are signed. Adding the unsigned keyword makes them unsigned.
There's an additional point here that's not mentioned: char, signed char, and unsigned char are distinct types, but that's only true of char. That is, signed int describes the same type as int. You can see this using the std::is_same type-trait with a conforming compiler. Whether char behaves like a signed integer type or an unsigned integer type, depends on the platform.
> Signed numbers may be encoded in binary as two’s complement, ones’ complement, or sign-magnitude; this is implementation-defined.
This is no longer true of C++. As of C++20, signed integer types are defined to use two's complement. [0] I don't think C intends to do the same.
> Character literals (in single quotes) have the type (signed) int in C, but (signed or unsigned) char in C++.
That's not correct. In C++, the type of a character literal is simply char, never signed char nor unsigned char. As I mentioned above, whether char is signed depends on the platform, but it's always a distinct type.
> Signed division can overflow – e.g. INT_MIN / -1.
This isn't just overflow, it's undefined behaviour.
> Counting down
> Whereas an unsigned counter would require code like:
> for (unsigned int i = len; i > 0; i--) { process(array[i - 1]); }
That's one solution, but it might be a good place for a do/while loop.
Then g should end up equal to 7. That's true even if you change the type of the cp parameter to const char*! If you change "char" to "unsigned char" in both places then its behaviour stays the same, but if you change it to "signed char" in both places then it has undefined behaviour (if I've remembered everything correctly). Now I think about it, this conflation of char's use in the C standard has probably prevented a lot of optimisations where code was just using char* for strings rather than for potential aliasing.
Another point, which is very related, is that uint8_t and int8_t do not necessarily have to be a typedef for unsigned char / signed char or char, even if char is 8 bits wide. So you could end up with (at least) 5 types that are 8-bit wide!
Combined with the above aliasing rules only applying to char and unsigned char, that means you cannot reliably expect uint8_t to have that aliasing exception. Indeed, gcc originally made a new type of uint8_t and int8_t but that caused so many bugs that they ended up switching them to unsigned char and char (and I think Visual Studio has always done so).
> > Character literals (in single quotes) have the type (signed) int in C, but (signed or unsigned) char in C++.
> That's not correct. In C++, the type of a character literal is simply char, never signed char nor unsigned char.
I was going to bring this up too, although I wouldn't quite say it's outright incorrect because I'm not sure they were making the claim you think they were - it could be interpreted to mean that it's always char in C++ but by the way don't forget that could be a signed or unsigned type (note the lack of monospace font for their use of "signed" and "unsigned"). But probably best not to overanalyse it since they probably didn't know the types were distinct - the main thing is reiterate, as you've done, that it's always `char` regardless of whether that's signed or unsigned.
I think saagarjha's point was that the article already points out that signed overflow causes undefined behaviour. That's true, but I think it still bears emphasising that (INT_MIN / -1) causes undefined behaviour.
> This is no longer true of C++. As of C++20, signed integer types are defined to use two's complement. [0] I don't think C intends to do the same.
As no good language lawyer discussion should be free from pedantry, there is no such thing as "As of C++20". C++20 is just a new version of the C++ standard. Projects that target C++11 or C++14 or C++17 are all still here and won't go away any time soon, and the respective C++ rule still apply to them. Passing a new revision of the C++ standard changes nothing with regards to which rules actually apply to those projects, unless project maintainers explicitly decide to migrate their projects.
Other reasons why a committee may decide to propose a standard for withdrawal include the following :
▸ ▸ the standard does not reflect current practice or research
▸ ▸ it is not suitable for new and existing applications (products,
systems or processes)
▸ ▸ it is not compatible with current views and expectations
regarding quality, safety and the environment
> floating-point number types will not be discussed at all, because that mostly deals with how to analyze and handle approximation errors that stem from rounding. By contrast, integer math is a foundation of programming and computer science, and all calculations are always exact in theory (ignoring implementations issues like overflow).
Integer overflow is no mere implementation issue, any more than errors are an implementation issue with floating-point.
> Unqualified char may be signed or unsigned, which is implementation-defined.
> Unqualified short, int, long, and long long are signed. Adding the unsigned keyword makes them unsigned.
There's an additional point here that's not mentioned: char, signed char, and unsigned char are distinct types, but that's only true of char. That is, signed int describes the same type as int. You can see this using the std::is_same type-trait with a conforming compiler. Whether char behaves like a signed integer type or an unsigned integer type, depends on the platform.
> Signed numbers may be encoded in binary as two’s complement, ones’ complement, or sign-magnitude; this is implementation-defined.
This is no longer true of C++. As of C++20, signed integer types are defined to use two's complement. [0] I don't think C intends to do the same.
> Character literals (in single quotes) have the type (signed) int in C, but (signed or unsigned) char in C++.
That's not correct. In C++, the type of a character literal is simply char, never signed char nor unsigned char. As I mentioned above, whether char is signed depends on the platform, but it's always a distinct type.
> Signed division can overflow – e.g. INT_MIN / -1.
This isn't just overflow, it's undefined behaviour.
> Counting down
> Whereas an unsigned counter would require code like:
> for (unsigned int i = len; i > 0; i--) { process(array[i - 1]); }
That's one solution, but it might be a good place for a do/while loop.
[0] https://stackoverflow.com/q/57363324/