Live data from Hacker News

Unsigned sizes: A five year mistake

c3-lang.org

91–100 of 153 posts

Re: Unsigned sizes: A five year mistake

#91

Finally a language doing the right thing :) My two ruls of thumb for C code are: 1. use signed integers for everything except bit-wise operations and modulo math (e.g. "almost always signed") 2. make implicit sign conversion an error via `-Werror -Wsign-conversion` The problem with making sizes and indices unsigned (even if they can't be negative) is that you'd might to want to add negative offsets, and that either r…

But a blog doing the wrong thing. Who decided that light grey on white was a great way to present text?

For anyone else struggling to read it, Ctrl-A will make it legible.

Re: Unsigned sizes: A five year mistake

#92
post #89

It's not really signed vs unsigned that's the issue, IMO. It's (mostly, in C) undefined behavior and implicit conversions? I'm not sure Go is saner just because len is an int. Well, maybe, depending on how you look at it. Defining len to be signed int, means the largest valid len is half your address space, which also means half of all possible indexes are always invalid; which makes some things easier. But it's real…

For signed overflow we have sanitizers, and for conversions C compilers warnings in C. Bounds checking can also be done with sanitizers (but is a bit more tricky). So no, I do not think the undefined behavior is really a big problem. In fact, it helps us find the problem because every overflow can be considered a programming error.

Error due to unsigned wraparound are a much bigger issue, because the lead to subtle issues where neither automatic warnings nor sanitizers help, exactly because it is well-defined and no automatic tool can tell whether the behavior is intended or wrong.

Re: Unsigned sizes: A five year mistake

#93
post #86
post #67

Earlier quoted context omitted.

Java has char as an unsigned 16-bit integer type. They should have made byte unsigned as well.

Usually you don't do arithmetic with char in Java, this isn't C culture of anything goes.

It is not even possible to do arithmetic on char in C.

Re: Unsigned sizes: A five year mistake

#94

Earlier quoted context omitted.

Why does an unsigned type for sizes or indices fare worse than a signed type? When do I want the -247th element in an array? When do I have a block that is -10 bytes in size?

There are (rare) times when you want negative array indices. C lets you index in both directions from a pointer to the middle of an array. That's why array indexing is signed in C. Some libc ctypes lookup tables do this. For sizing there is no strong case for negatives other than to shoehorn them into signed operations.

>That's why array indexing is signed in C

C23 updated the definition of the [] operator to disallow negative subscripts with array type. I think you have to explicitly convert the array to a pointer type now.

    int a[2];
    a[-1]; // not ok
    (&a[0])[-1] // ok
C23: https://cstd.eisie.net/c2y.html#6.5.3.2

C11: https://port70.net/~nsz/c/c11/n1570.html#6.5.2.1

Re: Unsigned sizes: A five year mistake

#95
post #36

Earlier quoted context omitted.

> That's true for signed numbers too though? `int_min - 2 > int_min` No, that's undefined behavior in C, and if you care about correctness, you run at least your testsuite in CI with -ftrapv so it turns into an abort().

Which makes them even less safe than unsigned, where it is defined, yes? The optimizations that can lead to are incredibly hard to predict. Besides, for safety there are much clearer options, like wrapping_add / saturating_add. Aborting is great as a safety tool though, agreed - it'd be nice if more code used it.

You can have the trap during production, and then it is safer. If you need to catch the problem at run-time, there are checked integer options in C that you can use.

Re: Unsigned sizes: A five year mistake

#96
post #92
post #89

It's not really signed vs unsigned that's the issue, IMO. It's (mostly, in C) undefined behavior and implicit conversions? I'm not sure Go is saner just because len is an int. Well, maybe, depending on how you look at it. Defining len to be signed int, means the largest valid len is half your address space, which also means half of all possible indexes are always invalid; which makes some things easier. But it's real…

For signed overflow we have sanitizers, and for conversions C compilers warnings in C. Bounds checking can also be done with sanitizers (but is a bit more tricky). So no, I do not think the undefined behavior is really a big problem. In fact, it helps us find the problem because every overflow can be considered a programming error. Error due to unsigned wraparound are a much bigger issue, because the lead to subtle i…

> Error due to unsigned wraparound are a much bigger issue

This is a type design mistake. The unsigned integers should not wrap by default. It makes absolute sense, given all the constraints and the fact that it's doing New Jersey "implementation simplicity dominates" design that K&R C only provides a wrapping unsigned type, but that's an excuse for K&R C which is a 1960s programming language.

The excuse gets shakier and shakier the further you move past that. C3 even named these types differently, so they're certainly under no obligation to provide the wrapping unsigned integers as if that's just magically what you mean. In most cases it's not what you mean. The excuse given in the article is way too thin.

Rust's Wrapping is the same thing as the wrapping 32-bit unsigned integer in C or C++ today, but most people don't use it because they do not actually want the wrapping 32-bit unsigned integer. This is a "spelling matters" ergonomics class again like the choice to name the brutally fast but unstable general comparison sort [T]::sort_unstable whereas both C and C++ leave the noob who didn't know about sort stability to find out for themselves because they name this just "sort" and you get to keep both halves when you break things...

Re: Unsigned sizes: A five year mistake

#97
So his compiler cannot detect the unsigned overflows and instead chooses to call it a user mistake!

Sizes and indices of course need to be unsigned, and any self respecting compiler should warn about dangerous usage.

Re: Unsigned sizes: A five year mistake

#98
post #92

Earlier quoted context omitted.

For signed overflow we have sanitizers, and for conversions C compilers warnings in C. Bounds checking can also be done with sanitizers (but is a bit more tricky). So no, I do not think the undefined behavior is really a big problem. In fact, it helps us find the problem because every overflow can be considered a programming error. Error due to unsigned wraparound are a much bigger issue, because the lead to subtle i…

> Error due to unsigned wraparound are a much bigger issue This is a type design mistake. The unsigned integers should not wrap by default . It makes absolute sense, given all the constraints and the fact that it's doing New Jersey "implementation simplicity dominates" design that K&R C only provides a wrapping unsigned type, but that's an excuse for K&R C which is a 1960s programming language. The excuse gets shakie…

Unsigned is certainly a misnomer for a wrapping type. That does not mean it is a type design mistake. And I agree that people should not use it much.

But what I do not believe is that there is a real need for a non-wrapping non-negative integer type.

Re: Unsigned sizes: A five year mistake

#99
post #98

Earlier quoted context omitted.

> Error due to unsigned wraparound are a much bigger issue This is a type design mistake. The unsigned integers should not wrap by default . It makes absolute sense, given all the constraints and the fact that it's doing New Jersey "implementation simplicity dominates" design that K&R C only provides a wrapping unsigned type, but that's an excuse for K&R C which is a 1960s programming language. The excuse gets shakie…

Unsigned is certainly a misnomer for a wrapping type. That does not mean it is a type design mistake. And I agree that people should not use it much. But what I do not believe is that there is a real need for a non-wrapping non-negative integer type.

> But what I do not believe is that there is a real need for a non-wrapping non-negative integer type.

So the most obvious counter example is so obvious you might not even have remembered it's a type, the unsigned 8-bit integer or byte.

But frankly if you don't have the wrapping mistake they just make for a pretty good general purpose index, they're a useful counter, there's a reason we called these the "Natural numbers".

Re: Unsigned sizes: A five year mistake

#100
post #87

Earlier quoted context omitted.

I find it the opposite. Unsigned integers are intuitive, while signed integers are unintuitive and cause a lot of tricky bugs. Especially in languages, where signed overflow is undefined behavior. It's pretty rare to have values that can be negative but are always integers. At least in the work I do. The most common case I encounter are approximations of something related to log probability. Such as various scores in…

It is interesting that you find unsigned integers more intuitive. My experience (also with students, but also analysis of CVE give plenty of evidence) is that the opposite is true: signed integers in C are a model of integers which have a nice mathematical structure which people learn in elementary school. Yes, this breaks down on overflow, but for this you have to reach very high numbers and there is very good tooli…

I work in bioinformatics. The numbers are typically large enough that you either have to think about numeric limits all the time if you use 32-bit integers (or bit-packed arrays), or you end up wasting (tens of) gigabytes with 64-bit integers.

I've also done a lot of succinct data structures, data compression, and things like that. When you manipulate the binary representation directly, it's easier to connect representation to unsigned semantics than to signed semantics.

Unsigned integers are usually integers modulo 2^n, which gives them a convenient algebraic structure. Whether you find that intuitive or not probably depends on your education. From my perspective, abstract algebra and discrete mathematics are things you learn in the first year of your CS degree.

Post reply on HN