Live data from Hacker News

Almost Always Unsigned

graphitemaster.github.io

31–40 of 103 posts

Re: Almost Always Unsigned

#31

Stroustrup recommends int over unsigned. Dijkstra recommends int over unsigned. Google coding guidelines recommend int over unsigned. Blogger recommends unsigned over int. Tough choice.

Commenter implies authority dictates strategy. We should be engaging with the article's content.

Actually, in that case, no.

Blogger hasn't bothered to refer to those well known and detailed opinions, from very experienced authorities, and provide detailed rebuttal to those authorities claims, so his opinion can be safely ignored.

Re: Almost Always Unsigned

#32

Stroustrup recommends int over unsigned. Dijkstra recommends int over unsigned. Google coding guidelines recommend int over unsigned. Blogger recommends unsigned over int. Tough choice.

ClickHouse code style recommends unsigned in every case when you don't need the sign: https://clickhouse.com/docs/development/style

No. It says the reverse: "11. unsigned. Use unsigned if necessary."

Unsigned is necessary only if you're working with bit fields, bit masks or require explicit modulo n-bit arithmetic.

For all other cases, use signed

Re: Almost Always Unsigned

#33
post #18

Stroustrup recommends int over unsigned. Dijkstra recommends int over unsigned. Google coding guidelines recommend int over unsigned. Blogger recommends unsigned over int. Tough choice.

signed overflow (or underflow) is frequently undefined behavior. (often because it's undefined in C) unsigned is frequently defined. (often because it's defined in C) tough choice. (honestly I just lean towards "over/underflow should raise unless explicitly allowed", the ratio of unintended to intended-and-fully-checked overflow behavior is almost certainly FAR beyond 100:1)

Of course unsigned is defined. That's besides the point. The point is: how often in your code, do you expect 1 minus 2 to equal a very large number, vs. the number -1.

Re: Almost Always Unsigned

#34

Earlier quoted context omitted.

I really don't see what's supposedly awful about that loop, but if you want to count down to x instead of 0 you just do: for (size_t i = size - 1; i >= x; i--)

> I really don't see what's supposedly awful about that loop The stopping condition is incredibly confusing and non-obvious. Misleading at first glance, in fact. The whole thing is so unidiomatic that I don't think I've even seen it once in my life. It's a better contender for an underhanded C++ code contest than production code. > but if you want to count down to x instead of 0 you just do i >= x No you can't. That…

Thinking of it as a "stopping condition" is backwards, that part of the loop is called the invariant:

https://en.wikipedia.org/wiki/Loop_invariant

You should think of it as the condition that's true for all iterations, not a one-time event that halts the loop. The loop is short for this:

  for(size_t i = size - 1; 0 
Which works for both signed and unsigned numbers. It just so happens that for unsigned numbers you can omit the left-hand side of the &&, and for signed numbers you can omit the right-hand side. To support arbitrary lower bounds, you omit neither.

Re: Almost Always Unsigned

#35
post #18

Earlier quoted context omitted.

signed overflow (or underflow) is frequently undefined behavior. (often because it's undefined in C) unsigned is frequently defined. (often because it's defined in C) tough choice. (honestly I just lean towards "over/underflow should raise unless explicitly allowed", the ratio of unintended to intended-and-fully-checked overflow behavior is almost certainly FAR beyond 100:1)

Of course unsigned is defined. That's besides the point. The point is: how often in your code, do you expect 1 minus 2 to equal a very large number, vs. the number -1.

both seem equally undesirable to me in all cases where I intend neither. though one also risks undefined behavior, so that is strictly worse.

the reason I use a type system is to make error classes unrepresentable (where possible) or a failure. these are both leaky abstractions in the worst possible manifestation: silent misbehavior at runtime.

Re: Almost Always Unsigned

#36
post #30
post #24

Earlier quoted context omitted.

that argument (and many others) also round to essentially "implicit imprecise integer casting is surprising but we do it anyway" which is... perhaps the actual problem??? I've made lints for Go that simply disallow implicit number casting, and omfg the (real, occurring but unnoticed) bugs it found. those kinds of lints are trivial to build, you can just stop doing it . forcing visible casts made many of these problem…

I believe there's ways to configure clang to flag dangerous implicit casts as well.

-Wconversion perhaps: https://clang.llvm.org/docs/DiagnosticsReference.html#wconve... or -Wimplicit-int-conversion for the main check I've built in other languages (afaict, I have not used C(++) professionally)

Re: Almost Always Unsigned

#37

Earlier quoted context omitted.

I really don't see what's supposedly awful about that loop, but if you want to count down to x instead of 0 you just do: for (size_t i = size - 1; i >= x; i--)

> I really don't see what's supposedly awful about that loop Exactly! That's precisely the problem with it. (Hint: think about your code when size = 0.)

It works perfectly fine for size = 0?

Re: Almost Always Unsigned

#38

Earlier quoted context omitted.

> I really don't see what's supposedly awful about that loop The stopping condition is incredibly confusing and non-obvious. Misleading at first glance, in fact. The whole thing is so unidiomatic that I don't think I've even seen it once in my life. It's a better contender for an underhanded C++ code contest than production code. > but if you want to count down to x instead of 0 you just do i >= x No you can't. That…

Thinking of it as a "stopping condition" is backwards, that part of the loop is called the invariant: https://en.wikipedia.org/wiki/Loop_invariant You should think of it as the condition that's true for all iterations, not a one-time event that halts the loop. The loop is short for this: for(size_t i = size - 1; 0 Which works for both signed and unsigned numbers. It just so happens that for unsigned numbers you can o…

> You should think of it as the condition that's true for all iterations, not a one-time event that halts the loop.

(a) It's "a" condition that holds true for all iterations, not "the" condition. Plenty of other conditions can hold true across the iterations of any given loop too. In fact the one interesting thing about the loop invariant compared to any other conditions is the very fact that it is guaranteed to cease to hold immediately after the loop, assuming you don't break in the loop. Other conditions can still continue to hold. i.e. The stopping condition is the entire point of the loop invariant.

(b) I'm well aware what a loop invariant is; I've worked on compilers. I am also a human. Humans care about when a loop starts and stops. There's nothing backwards about it, it's the most straightforward way people think of loops. And it's literally why more modern languages have introduced better syntaxes that merely spell the boundaries and/or values, and skip spelling the invariants entirely.

Re: Almost Always Unsigned

#39
post #20

Earlier quoted context omitted.

I liked how the discussion of 'delta = x - y' moved right on to how really you usually want delta = abs(x - y), so let's talk about that instead... Even beyond Stroustrup, Dijkstra, and Google, this whole panel of C++ luminaries agrees to prefer signed types and explains pretty clearly why: - 12:12-13:08 - https://www.youtube.com/watch?v=Puio5dly9N8#t=12m12s - 42:40-45:26 - https://www.youtube.com/watch?v=Puio5dly9N8…

Thanks for the excerpts! I was trying to understand the reasoning, which seem to just be in the 2nd excerpt: - The rules of signed/unsigned are complicated and there is too much auto-conversion - does that mean languages that make this more explicit means this is fine? It just seems ideal to have stronger typing. - It is mentioned that you can initialized an unsigned int to "-2" - but that presumably could also be fi…

Considering Rust doesn’t have such nonsense, I’m inclined C/C++ have utterly broken generations of programmers.

In what world is using a signed value to index a normal array a good idea?

Makes for horrible footguns like:

history[counter % SIZE] = …

(One cursed day counter rolls over, becomes negative, and an out-of-bounds write occurs)

Everything went South as soon as we broke the abstraction of arrays and treated them as pointers.

Commenters here are pretty much arguing which way to hold scissors while running instead of realizing that one shouldn’t do that in the first place…

Re: Almost Always Unsigned

#40

Earlier quoted context omitted.

Commenter implies authority dictates strategy. We should be engaging with the article's content.

Actually, in that case, no. Blogger hasn't bothered to refer to those well known and detailed opinions, from very experienced authorities, and provide detailed rebuttal to those authorities claims, so his opinion can be safely ignored.

Commenter comments before reading.

The entire article literally starts by referring to Google coding guidelines and other well known opinions as arguments against unsigned, then tries to provide a rebuttal.

Post reply on HN