Remix.run Logo
einpoklum 13 hours ago

It's not "can't be negative", it's just that the semantics for negativity is wrapping around.

And - yes, there are very important use cases for unsigned/modulo-2n/wraparound values. But sizes of data structures are generally _not_ one of those use cases. The fact that the size is non-negative does not mean that the type should be unsigned. You should still be able to, say, subtract sizes and get a signed value which may be negative.

throwaway894345 13 hours ago | parent [-]

That’s definitely not true. Unsigned ints have no “negativity” semantic. Wrapping around is what happens when you decrement the minimum value of any integer type, including signed types. Regardless of the type you use to represent an integer value that cannot legally be negative, you will have to take care not to allow your program to return values lower than zero for things like indices or sizes.

oasisaimlessly 12 hours ago | parent | next [-]

> Wrapping around is what happens when you decrement the minimum value of any integer type, including signed types.

No, signed wraparound is undefined behavior in C, whereas unsigneds are defined to wraparound. If you use -ftrapv, signed wraparound is an immediate abort().

adrian_b 12 hours ago | parent | next [-]

That is right.

While C like in many other places fails to define the correct behavior to avoid shaming the processor or compiler makers that fail to provide it, there are only 2 correct behaviors on overflows and underflows, like when incrementing the biggest number or decrementing the smallest number.

Both for signed integers and for non-negative integers, the 2 alternatives of correct behavior on overflows and underflows is to either generate exceptions or to saturate the result to the biggest or smallest representable number.

Wraparound is the correct behavior for integer residues, which are a distinct data type from either signed integers or non-negative integers.

While some people criticize C for making easy for careless programmers to make certain kinds of bugs, like access outside bounds, those are easily mitigated by using appropriate compiler options.

For me a much more serious defect of C is this confusion promoted by it in the heads of most programmers, who do not understand which are the fundamental integer types and which are the correct conversions between them, because C uses "unsigned" instead of at least 3 distinct types that it does not have, bit strings, integer residues and non-negative integers. More rarely, "unsigned" is used for other 2 types that are missing, binary polynomials and binary polynomial residues. All these 5 types must be primitive types in a programming language because all modern processors implement in hardware distinct operations for all 5 types, which can be accessed only through assembly language when these types are missing.

akkartik 11 hours ago | parent [-]

When I was building my computing stack out of x86 machine code I noticed that even if my high level language only had signed numbers (I'm still pretty brainwashed by C, which leads to the conclusions of OP), I still needed the ISA's unsigned jumps to deal with addresses (which can have the MSB set). So my big "insight" was to name unsigned comparisons "address comparisons".

https://akkartik.github.io/mu/html/mu_instructions.html

throwaway894345 9 hours ago | parent | prev [-]

This feels like you’re trying to “gotcha” me, but I didn’t say C specifies 2s complement wraparound, I said that’s what happens in virtually every language (including the major C/C++ implementations). It seems like you are “violently agreeing” with me.

einpoklum 10 hours ago | parent | prev [-]

> Unsigned ints have no “negativity” semantic.

They do. The code:

    unsigned x;
    unsigned y = -x;
is well-defined in C and C++. See this discussion on StackOverflow for spec text and reference:

https://stackoverflow.com/q/8026694/1593077

throwaway894345 9 hours ago | parent [-]

That’s not a negativity semantic, it’s the behavior of the “-“ operator. If you print y or compare it to zero you will see that the result remains positive. Unsigned integers by definition have no negative semantic, hence the name.