[Dons language lawyer hat] > 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…
Summary of C/C++ integer rules
11–20 of 98 posts
Re: Summary of C/C++ integer rules
#12It’s funny that you would end up with a similar conclusion for other parts of the language (e.g. operators) as well. Just a gigantic set of inane rules everywhere causing you to constantly be in danger of introducing bugs and portability issues.
But! And that's important -- it allows for great performance, so you can make ten/hundred times more mistakes per second than in other, "safer" languages.
Re: Summary of C/C++ integer rules
#13> char is always 8 bits wide. int is always 32 bits wide
> Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.)
Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)?
E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions would apply?
Re: Summary of C/C++ integer rules
#14Earlier quoted context omitted.
But! And that's important -- it allows for great performance, so you can make ten/hundred times more mistakes per second than in other, "safer" languages.
Nowadays, it doesn't provide any performance gain. I didn't see those days but maybe it was important for performance back in 70s/80s/90s even it was risky? e.g null terminated string was chosen due to low space overhead.
Re: Summary of C/C++ integer rules
#15> Having signed and unsigned variants of every integer type essentially doubles the number of options to choose from. This adds to the mental burden, yet has little payoff because signed types can do almost everything that unsigned ones can. Unsigned types are quite useful when doing bit twiddling because they don't overflow or have a bit taken up by the sign.
That's essentially their only application. The rest are stupid single-bit memory-size optimizations. As Jens Gustedt noted, it's one of the (many) misnomers in the C language. It should be better called "modulo" instead of "unsigned". Other such misnomers that I recall:
unsigned -> modulo
char -> byte
union -> overlay
typedef -> typealias
const -> immutable
inline -> negligible
static -> intern
register -> addressless
EDIT: found the reference https://gustedt.wordpress.com/2010/08/18/misnomers-in-c/Re: Summary of C/C++ integer rules
#16In the myths section: > char is always 8 bits wide. int is always 32 bits wide > Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.) Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)? E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions wou…
Re: Summary of C/C++ integer rules
#17[Dons language lawyer hat] > 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…
That's correct, I was going to bring that up too.
This is particularly important because char and unsigned char are special in that they are an exception the aliasing rules. That is, in this function:
float foo(char* cp, float* fp) {
*fp = 7;
return *(float*)cp;
}
/* ... */
float f = 2;
float g = foo((char*)&f, &f);
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.
Re: Summary of C/C++ integer rules
#18Earlier quoted context omitted.
Nowadays, it doesn't provide any performance gain. I didn't see those days but maybe it was important for performance back in 70s/80s/90s even it was risky? e.g null terminated string was chosen due to low space overhead.
It depends on what you are doing. For some kinds of programs, C/C++ are going to be much faster than most "modern" languages.
What I meant is undefined behaviors allow compilers to optimize in a way that would not be possible otherwise. So, it might be a deliberate decision back then, to leverage performance. I don't know, just an idea.
Re: Summary of C/C++ integer rules
#19In the myths section: > char is always 8 bits wide. int is always 32 bits wide > Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.) Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)? E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions wou…
Certainly you can find an architecture which may run some type of C-like language with strange arithmetic rules (e.g. DSPs). I would bet it's harder to find one such architecture where one can run standard C, and impossible to find one which can run standard C++.
Re: Summary of C/C++ integer rules
#20In the myths section: > char is always 8 bits wide. int is always 32 bits wide > Signed overflow is guaranteed to be wrap around. (e.g. INT_MAX + 1 == INT_MIN.) Are there any current, relevant hardware architectures where this is not true (e.g. bytes are not 8 bits, and integers are not 2's complement)? E.g. what's the point of "portability" if there is no physical hardware around anymore where those restrictions wou…