Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

[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 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/



> char, signed char, and unsigned char are distinct types, but that's only true of char.

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.


>So you could end up with (at least) 5 types that are 8-bit wide!

Don't forget std::byte.


It is not a full-featured arithmetic type though. It doesn't implement operator+/-/* etc.


>> 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'd assume the author meant (signed `char` | unsigned `char`) rather than (`signed char` | `unsigned char`).


To put it better, I meant to write that C++ character literals have type `char`, which in turn maps to either `signed char` or `unsigned char`.


What is the reference to "Dons"?


Don is a somewhat uncommon verb, To put on clothing. https://en.wiktionary.org/wiki/don#Verb


Signed overflow is undefined behavior.


That seems to be exactly what the parent comment said.


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.


> C++20 is just a new version of the C++ standard.

and per ISO rules, older versions are withdrawn (as can be confirmed for C++ here: https://www.iso.org/standard/79358.html) and not to be used anymore: https://www.iso.org/files/live/sites/isoorg/files/store/en/P...

    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


Wow. Didn't know this. It doesn't have any bearing whatsoever on reality though. If it did, I wouldn't still be writing C++98 conformant C++.


well, your code is nonstandard, that is all, just like a house with powerplugs installed 30 years ago is not standard, even if it "works"




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: