frontpage.
newsnewestaskshowjobs

Open Source @Github

fp.

Open in hackernews

Almost Always Unsigned

https://graphitemaster.github.io/aau/
32•gavide•1d ago

Comments

pmarreck•21h ago
Related: I have a variable integer length encoding scheme that beats out LEB128, Protobuf, varint and ASN.1 while also encoding/declaring endianness (but notably, leaving signage information up to the application): https://github.com/pmarreck/BLIP
dataflow•21h ago
> for (size_t i = size - 1; i < size; i--)

Erm... just because you can, doesn't mean you should.

Also, what if you want to go down to something other than 0?

AlotOfReading•20h ago
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--)
dataflow•20h ago
> 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 fails if x == 0. Which perfectly illustrates why using unsigned everywhere isn't so great. And I say this as someone who likes unsigned types and uses them more than average!

wasmperson•18h ago
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 <= i && i < size; i--){
  
  }
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.
dataflow•16h ago
> 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.

StellarScience•20h ago
> 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.)

layer8•17h ago
It works perfectly fine for size = 0?
xigoi•14h ago
They meant x = 0.
layer8•14h ago
Not sure if they meant that, since the “awful” was referring to the original loop that had no x, but the generic solution in that case is:

    for (size_t i = size; i—- > x;)
StellarScience•20h ago
> for (size_t i = size - 1; i < size; i--)

Agreed, seeing that example briefly made me consider whether this blog post was a parody. Sure, it works for this exact example, by relying on i wrapping "down" to MAX_INT on the last iteration. But how long will it take the next developer who works on the code base to figure that out? Will they figure it out before or after committing changes that break it? Or worse yet, before or after shipping code?

nulltrace•20h ago
That loop reads like a bug to anyone who hasn't memorized the wrapping rules. while (i-- > 0) on a signed index does the same thing.
scared_together•21h ago
There was a related article from the other side of the debate a while back: https://news.ycombinator.com/item?id=47989154

It’s pretty sad that after all these years, dealing with fixed size integers is still so complicated. Yes, many of the problems are specific to low level languages with undefined behaviour and numeric for loops. But the issue of subtracting two numbers and possibly having an underflow is both common and a bit absurd.

The code in the article for “safely” calculating the difference of two unsigned numbers, which is simpler than the equivalent for signed integers, is this little ritual:

> delta = max(x, y) - min(x, y);

Seriously??? Two function calls just for the difference of two numbers??

Why can’t such “safe” operations have some of the sweet syntactic sugar, and the underflow-rampant “ordinary” operations have the bitter medicine of ritual?

tialaramex•21h ago
I mean, Rust calls this function you want abs_diff

    let a = 1234_u32;
    let b = 5678_u32;
    let c = a.abs_diff(b); // Or equivalently u32::abs_diff(a, b);
Some languages hate offering convenience functions, in particular in a language like C or one of the would-be C-replacements, those functions just clog up the same namespace as everything else, so having 100 intrinsic arithmetic functions for integers feels disproportionate. The C-like languages, even those which do have methods, often forbid methods on their "built-in" or "core" types like integers so they can't do what Rust did here.

Edited: tweaked language

jandrewrogers•20h ago
The issue is that you need dozens of minor variants for the myriad cases involving integers, especially in C. That namespace becomes rather busy.

This particular idiom for finding the absolute difference of an unsigned integer pair is pretty clean and rarely needed. In most contexts you know that one argument will always be greater than or equal to the other, so a simple subtraction will do.

tialaramex•21h ago
Should be (2022) apparently - surely if HN can automatically screw up titles for various reasons, we can have it add dates automatically [and sometimes get those wrong] too? DanG ?

> for instance C and C++ leave signed integer wrap undefined

I'm pretty sure the way to write what was meant here is "C and C++ leave signed integer overflow undefined". Wrapping would be a definite choice. Overflow is the situation we're considering, not a particular outcome to choose so that is what's undefined.

The confusion gets worse later when it insists that just like in C or C++ these three Rust expressions will produce invalid results because of LLVM:

    x / 0
    INT_MIN / -1
    INT_MAX % -1
    INT_MAX - INT_MIN
Assuming we defined INT_MAX and INT_MIN as say i32::MAX and i32::MIN (or whichever signed type you prefer) of course what these actually do in Rust is just panic. If you write this in a context where it'll be evaluated at compile time, your compilation fails. That's not "invalid" in any sense I understand.

It mentions Odin too, I know less about Odin but I believe it too will reject this nonsense, on Godbolt it seems to either SIGILL (for zero) or SIGFPE (for other impossible operations)

Edited: Apparently I copy-pasted wrong? Some of those invalid expressions were not as written on the blog post but are now hopefully fixed. They are, of course, still not invalid in Rust, some panic because they aren't valid questions (like dividing by zero), others are fine - neither case is a problem.

gumby•20h ago
> for instance C and C++ leave signed integer wrap undefined

Not in C++29, and I think the big 3 compilers (gcc, clang, MS) will have squashed this long before that version is officially approved.

tialaramex•20h ago
> Not in C++29

C++ 29 doesn't yet exist. It'll be finalised in (as its name suggests) 2029. Are you referring to some proposal you think has been accepted? Or is this one of those "I have concepts of a proposal?" ideas where you confused wishful thinking with reality ?

dataflown•21h ago
Stroustrup recommends int over unsigned. Dijkstra recommends int over unsigned. Google coding guidelines recommend int over unsigned.

Blogger recommends unsigned over int.

Tough choice.

StellarScience•20h ago
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#t=42m40s

- 1:02:50-1:03:15 - https://www.youtube.com/watch?v=Puio5dly9N8#t=1h2m50s

nazcan•20h ago
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 fixed in the language.

I'm trying to separate out which is "don't do this in C/C++" and which is "don't do this in any language".

Groxx•20h ago
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 problematic patterns extremely suspicious at a glance, catching issues at review time far more easily.

cpeterso•20h ago
There was a golang proposal to change Go's default int type to arbitrary precision big int. It would avoid overflow bugs, but the proposal was closed (after eight years) due to concerns about compatibility reading serialized data and performance.

https://github.com/golang/go/issues/19623

Groxx•20h ago
as much as I'm not really a fan of Go, and I would love to spend some time in a language that defaults to unsigned ints by default to see just how pleasant or painful it really is, I do think Go makes a reasonable tradeoff here.

signed ints are rather obviously the majority decision, so that default is defensible, and their const / compile-time math is arbitrary precision. so as long as you can describe your math as either wholly const or can move all overflow-risky stuff into a const equation, you're good - Go's compiler will fail if it exceeds the bounds of whatever number you try to cast it to (implicitly or explicitly).

ignoring fun with float rounding, of course.

bogdanoff_2•20h ago
You can count down to zero with while(i--)
pikuseru•19h ago
What if I’m making a 2d game and need to go left
jgtrosh•14h ago
> Where unsigned does benefit here is when these are used as indices into an array. The signed behavior will almost certainly produce invalid indices which leads to memory unsafety issues. The unsigned way will never do that, it’ll stay bounded, even if the index it produces is actually wrong. This is a much less-severe logic bug, but can still be used maliciously depending on context.

The argument for signed often goes that it's easier to detect an invalid operation on an index by checking for bounds, or the higher probability of segmentation faults, than if your index is always “valid”. Granted, even with signed your invalid operation might still give a valid index. Simply put, seeing a negative index in your debugger is an obvious red flag you lose with unsigned.

In general I want to complain about the idea that a subtle bug is less severe than an obvious bug. Obvious bugs can be caught automatically or manually and are therefore less severe than subtle ones. This is a mistakes all students do btw. Segmentation faults are your friends!

karussell•9h ago
As a Java developer I'm a bit sad that we don't have a choice :)
xyzzyz•19h ago
For the stuff I do, I rarely use signed types. I find the example of finding difference between two numbers to be really silly. I don’t recall ever having to do anything like that, for a simple reason: I design my code so that I always know which number will be larger than the other.

Let’s actually talk more about this max - min example. Let’s say you calculated this delta. What is it useful for in your code? Typically, in real algorithms, what you want is to not only know the delta, but also which number is larger.

scared_together•11h ago
> I design my code so that I always know which number will be larger than the other.

That’s good discipline, but with better tooling and languages such conditions could be enforced by the compiler such as with Dafny. But Dafny is overkill for those who only want to avoid underflow and overflow without verifying everything else about their program…

That’s what I mean when I lament the state of affairs for underflow. Subtracting numbers is such a basic operation, but for the tech stacks used by most teams it still requires a level of care to avoid errors or corruption. Our industry is building million line behemoth codebases but these basic operations still have to be designed around.

> Typically, in real algorithms, what you want is to not only know the delta, but also which number is larger.

I agree with you, and the article was more concerned about avoiding underflow than actually having a practical use for its various example idioms.

What I’d actually prefer is a guarantee that subtracting two (X) bit numbers results in an (X+1) bit number. A sort of compile-time-checked bignum implementation where the programmer never thinks about the integer sizes or which number is larger until the final step of a calculation. Obviously this gets wasteful when multiplying numbers several times. EDIT: and I’m referring to an abstraction of integer bit sizes in a programming language, I’m not expecting the instruction set or hardware to have arbitrary sized registers.

leecommamichael•19h ago
https://odin-lang.org/docs/overview/#integer-overflow

> For signed integers, the operations +, -, *, /, and << may legally overflow and the resulting value exists and is deterministically defined by the signed integer representation. Overflow does not cause a runtime panic. A compiler may not optimize code under the assumption that overflow does not occur. For instance, x < x+1 may not be assumed to be always true.

tialaramex•4h ago
You've linked Odin's documentation. It's good to have documentation, but, because Matt Godbolt is a nice guy we can just try it out and see for ourselves

https://odin.godbolt.org/z/4WezGr7nK

In Odin, Dividing the 16-bit signed integer -32768 by -1 results in taking SIGFPE. Maybe it's not documented to do that, but that's what happens.

a_t48•19h ago
I believe there's ways to configure clang to flag dangerous implicit casts as well.
Groxx•18h ago
-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)
BobbyTables2•16h ago
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…

xigoi•14h ago
> Makes for horrible footguns like:

> history[counter % SIZE] = …

The footgun here is that the “modulo” operator does not actually calculate the modulo in C. In Python, this works correctly for negative values.

masklinn•12h ago
> In Python, this works correctly for negative values.

They’re both “broken” in different ways. Arguably C’s brokenness is more apparent and less useful but Python also has footguns: C uses truncated division for its “modulo” so the remainder has the sign of the dividend, Python uses floored division so the remainder has the sign of the divisor instead.

The wiki page for modulo has a pretty extensive page on the subject.

Groxx•20h ago
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)

dataflown•18h ago
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.
Groxx•18h ago
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.

leecommamichael•19h ago
Commenter implies authority dictates strategy.

We should be engaging with the article's content.

dataflown•19h ago
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.

orbital-decay•15h ago
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.

AlexClickHouse•19h ago
ClickHouse code style recommends unsigned in every case when you don't need the sign: https://clickhouse.com/docs/development/style
dataflown•18h ago
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

GPT-5.6

https://openai.com/index/gpt-5-6/
647•logickkk1•2h ago•446 comments

ChatGPT Work

https://openai.com/index/chatgpt-for-your-most-ambitious-work/
233•Tiberium•2h ago•99 comments

GLM 5.2 is nearly as accurate as a human book keeper

https://toot-books.pages.dev/blog/glm-5-2-vat-benchmark
56•adamkurkiewicz•1h ago•26 comments

Show HN: 18 Words

https://18words.com/
658•pompomsheep•6h ago•244 comments

EU Parliament greenlights Chat Control 1.0

https://www.patrick-breyer.de/en/eu-parliament-greenlights-chat-control-1-0-breyer-our-children-l...
688•rapnie•8h ago•352 comments

Hy3

https://hy.tencent.com/research/hy3
224•andai•4h ago•62 comments

Buried Apple Feature Turns an iPhone into the Perfect Kids' Dumb Phone

https://www.wired.com/story/this-buried-apple-feature-turns-an-iphone-into-the-perfect-kids-dumb-...
97•PotatoNinja•3d ago•53 comments

A possible future for Damn Interesting

https://www.damninteresting.com/a-possible-future/
138•mzur•4h ago•12 comments

Girls Just Wanna Have Fast MPMC Queues with Bounded Waiting

https://nahla.dev/blog/waitfree_queue/
73•EvgeniyZh•2d ago•11 comments

TLS certificates for internal services done right

https://tuxnet.dev/posts/tls-for-internal-services/
91•mrl5•4h ago•61 comments

Wildcard (YC W25) Is Hiring a Founding Engineer

https://www.ycombinator.com/companies/wildcard/jobs/ZSLVaaU-founding-engineer
1•kaushikmahorker•2h ago

The glass backbone: Why the Army's logistics will break in the next war

https://mwi.westpoint.edu/the-glass-backbone-why-the-armys-logistics-will-break-in-the-next-war/
201•baud147258•6h ago•252 comments

Muse Spark 1.1

https://ai.meta.com/blog/introducing-muse-spark-meta-model-api/
243•ot•5h ago•144 comments

Launch HN: Context.dev (YC S26) – API to get structured data from any website

https://www.context.dev
50•TheYahiaBakour•4h ago•39 comments

No leap second will be introduced at the end of December 2026

https://datacenter.iers.org/data/latestVersion/bulletinC.txt
175•ChrisArchitect•5h ago•142 comments

How to Start a Ruby Meetup

https://guides.rubyevents.org/meetups/
19•mooreds•1h ago•4 comments

Opinionated and Easy Pi.dev Configuration

https://lazypi.org/
71•lwhsiao•4h ago•45 comments

Train SIM Created by Just One Person Is Being Called the Best Ever Made

https://kotaku.com/a-train-sim-created-by-just-one-person-is-being-called-the-best-ever-made-2000...
24•oumua_don17•4d ago•0 comments

Show HN: I mapped 8.5M research papers into an interactive atlas

https://tomesphere.com/atlas
34•leonickson•17h ago•7 comments

How should group chats work in decentralized systems?

https://marindedic.com/groups/
29•Realman78•2h ago•15 comments

Show HN: Analog Watch

https://analog.watch
72•ezekg•5h ago•64 comments

Meta reuses old RAM in new servers with custom bridge chip

https://www.networkworld.com/article/4192827/meta-reuses-old-ram-in-new-servers-with-custom-bridg...
257•ihsw•6d ago•174 comments

New open access book on history of computers and politics

https://mitpress.mit.edu/9780262053198/simpolitics/
45•mckelveyf•5h ago•4 comments

AI changes the economics of software rewrites

https://thetruthasiseeitnow.com/ai-slop-starts-with-the-codebase-itself/
78•cinooo•13h ago•85 comments

Spider venom kills varroa mites without harming honeybees

https://connectsci.au/news/news-parent/9703/Spider-venom-kills-varroa-mites-without-harming
271•Jedd•14h ago•122 comments

How to Follow a Drummer

https://drummate.app/blog/how-to-follow-a-drummer
10•sashyo•3d ago•12 comments

What is Bending Spoons? The little-known AOL and Vimeo owner that's now public

https://techcrunch.com/2026/07/05/what-is-bending-spoons-everything-to-know-about-aols-acquirer/
51•jack1689•3d ago•74 comments

What's slowing down the AI buildout

https://www.worksinprogress.news/p/ai-is-bottlenecked-by-the-grid
48•droidjj•16h ago•105 comments

Show HN: Devthropology – Better Insights for GitHub Repos

https://devthropology.com/demo
24•dpc94•2h ago•6 comments

Why the Next Era of AI Is About Infrastructure, Not Just Models

https://blog.mozilla.ai/the-control-layer-why-the-next-era-of-ai-is-about-infrastructure-not-just...
5•royapakzad•4h ago•0 comments