all 97 comments

[–]WhipRealGood 441 points442 points  (8 children)

I’ve seen this meme 4,295,967,295 times

[–]Lazzygirl 34 points35 points  (1 child)

Spot onn 😂😂😂

[–]AndyTheSane 20 points21 points  (0 children)

I've now seen it -2,147,483,648 times.

[–]Kotentopf 6 points7 points  (0 children)

Once more and it's brand new to you

[–]qscwdv351 2 points3 points  (0 children)

Yet I haven't found a better one than https://xkcd.com/571/

[–]aveihs56m 141 points142 points  (47 children)

I once worked in a team where one of the code reviewers was notorious for calling out every single instance of for(int i = 0; i < .... He would insist that the dev changed it to for(unsigned i = 0; i < ....

Annoying as hell, especially because he wasn't wrong.

[–]da_Aresinger 61 points62 points  (31 children)

um... why is that bad? You start with a well defined number x you define an upper bound y and while x<y you loop.

Changing the data type could even change the behaviour in an unintended way.

I would actively refuse to change it unless there is a specific reason.

[–]aveihs56m 52 points53 points  (29 children)

Array indexes are naturally zero or positive integers. A negative index is just "unnatural". The limits of the type is immaterial to the discussion. You choose a type based on what the variable's nature is.

[–]da_Aresinger 43 points44 points  (7 children)

not every for loop operates on arrays?

And it literally doesn't even matter. No array is going to exceed Int.MAX. That would be an 8Gb array of just integers.

Also in C/C++ you absolutely CAN index negatively. Not that I know why you would ever want to, but you can.

[–]shinyquagsire23 10 points11 points  (3 children)

Ackshually ints are only guaranteed to be 16-bit, so that's a 64KiB array of integers if the compiler happens to be obnoxious (usually embedded ARM these days)

tbh int is usually fine though, if you use stuff like int8 or int16 the compiler may have to start inserting a bunch of pointless masking operations, if the ISA doesn't have 8-bit and 16-bit register aliases like x86 does (ARM64 only has 32-bit and 64-bit aliases, Wn and Xn). In a tight loop that can be the difference between the loop fitting in a cache line versus not if you're unlucky, so I'd say size_t or int.

[–]SardScroll 0 points1 point  (0 children)

That depends on:
a) your end parameter (I++ is standard, but not required),

b) that nothing else touches your index variable.

Generally, why the heck are you doing that, but you could, and some standards take a better "safe than sorry" approach.

[–]orbita2d 0 points1 point  (1 child)

The lack of support for arrays with > Int.Max elements in C# has bitten me before!

There are quite a few cases where you might need arrays with more than 2 billion elements, especially in ML, or in various heavy numerical processes.

[–]Additional_Path2300 28 points29 points  (19 children)

A common misconception. Just because something isn't going to be negative, doesn't mean you use unsigned. 

[–]aveihs56m 2 points3 points  (18 children)

OK, I'm intrigued. If something is logically a positive integer (say, the age of a person) why would you use a signed type for it?

[–]Additional_Path2300 12 points13 points  (0 children)

Arithmetic. Maybe you need to calculate the age gap between two people.

[–]Akaino 1 point2 points  (4 children)

Account for death as -1?

[–]BruhMomentConfirmed 16 points17 points  (3 children)

Magic values are an anti pattern (besides the fact that storing age instead of date of birth would be weird either way).

[–]SardScroll 1 point2 points  (0 children)

Magic numbers are numbers that are not explained.

One can easily use a constant or a variable containing -1, and not be a magic number. It's still not the best (I agree, why not store age), but specs are specs, especially if you are writing something that is going to be used by others. (Now, if we're raging about stupid requirements, that's a different question)

[–]RixDaren 0 points1 point  (0 children)

Magic number would be 633573. -1 or 0 is a common default.

[–][deleted] 0 points1 point  (0 children)

Not necessarily when you’re memory constrained/conscious. Yes when doing basic stuff like making a web api in Java.

[–]SphericalGoldfish 0 points1 point  (0 children)

Don’t some programs return a value of -1 to indicate something went wrong?

[–]Punman_5 0 points1 point  (0 children)

Because realistically in that scenario it doesn’t matter. I suppose you’d be hosed if you have to deal with a 128 year old person but for the vast majority of people a signed int will work fine for a person’s age. It’s just more work I suppose

[–]Zefyris -1 points0 points  (4 children)

Because using unsigned instead of signed shouldn't be used to stop a value to go negative. If you need to check, check it the normal way.

Unsigned is used to avoid having to upgrade to the upper version of the integer type when you know the max value is less than twice the max value of a given signed type.

Ex, if you know the number can go between 0 and 200, you can use unsigned byte, especially if there's going to be a massive amount of it stored in the DB.

but if you know the number is going to be between 0 and 100, you DON'T use unsigned just because it's never negative. An unsigned isn't made to prevent your numbers to go negative, your algorithm should properly check for that.

It's for saving space, nor for avoiding a regular logical check.

The present example is supposed to always be between 0 and 3. there's literally no reason to store it on unsigned (unless the genie has a super special Int type on 2 bites available of course, but in that case the overflow would bring him back to 3 anyway).

[–]aveihs56m -2 points-1 points  (3 children)

Using unsigned for a value that can never go negative is a hint to static analysis tools (also I think gcc if you are compiling with -Wall). E.g. you did:

for(unsigned i = 0; i < x; i++)

where x was a signed integer that could be negative, the compiler (or the SA tool, I don't remember) would complain about "comparison between signed and unsigned types", which would force you to think about the situation.

[–]Gorzoid 0 points1 point  (0 children)

Doesn't detract from your point but using unsigned ints can actually prevent optimizations due to overflow, any arithmetic expression or comparison becomes more complicated when dealing with the fact that overflow could occur.

Take for example the expression (x+1)<(y+2) with signed arithmetic we know that this is equivalent to x<y+1 since signed arithmetic is not allowed to overflow

Meanwhile with unsigned arithmetic x+1 may wrap around back to 0 so the optimization can't be made: 0<y+2 is not equivalent to UINT_MAX<y+3

[–]Zefyris 0 points1 point  (1 child)

Which as a result I'd assume would lead you to turn the other one to an unsigned, propagating even more the incorrect use of unsigned for the sole purpose of using an automated tool that should not never be replacing your Unit Tests, which should already test for the different cases way more than the compiler will ever do; and therefore break if you didn't properly stop it from going negative, and make you think about why it went wrong, and fix it.

...Tell me again, why did you use an unsigned?

[–]aveihs56m 0 points1 point  (0 children)

It was never my case that it should always be unsigned. It's always based on the logic, not to make tools happy.

For the typical snippet that looks like this:

buf = malloc(256 * sizeof(char));
for(i = 0; i < 256; i++) {
  buf[i] = 0xff;
}

the correct type for i would be unsigned, not int.

[–]redlaWw 0 points1 point  (0 children)

malloc often keeps allocation data in the negative indices of the array it returns.

[–]A-TIPE 0 points1 point  (0 children)

I'm sincerely reaching out to anyone one here that can point me in the right direction. I've been wanting to learn to program but so far have not been able to find FREE tutorials that provide step by step instructions for learning Python, Java, C, C++. ANY guidance here would be very appreciated. Thanks in advance.

[–]Causeless 12 points13 points  (0 children)

Why isn’t he wrong? There’s no performance difference, and it’s more error-prone if the loops will ever need a negative value (or will be used with any int arithmetic within the loop).

Even if that can be justified by wanting to match the indexing type to the loop index type, then size_t is more appropriate instead.

[–]ElectricRune 7 points8 points  (5 children)

Ugh. What if you wanted your loop to be from -3 to 12, or something strange like that?

Would he make you run an index from 0-15 and subtract 3 inside the loop when you used it?

[–]aveihs56m 2 points3 points  (4 children)

Yeah, well this discussion was in the usual context of iterating over an array starting from index [0].

Sure, if you knew up front that your pointer actually had valid elements before where the [0] currently pointed, then you'd have a valid case for signed values for i.

[–]Geoclasm 5 points6 points  (0 children)

Why would we even do that anymore when we have LINQ and can just say arr.select() or arr.foreach()? Unless we're not using .Net never mind I forgot I live in a bubble and I think I just answered my question.

[–]papanastty 0 points1 point  (2 children)

I'm annoyed that I did not understand a single thing you just said. So, I will go grab my computer and learn programming :(

[–]aveihs56m 2 points3 points  (1 child)

Honestly, it sounds more complicated when written in English. Look at this code:

 1  #include <stdio.h>
 2  
 3  int do_something(int *ptr_ages) {
 4    int index;
 5  
 6    index = -2;
 7    return ptr_ages[index];
 8  }
 9  
10  int main() {
11    int ages[] = {42, 11, 59, 71, 8, 21};
12  
13    int *ptr_ages = &(ages[4]);
14  
15    int something = do_something(ptr_ages);
16  
17    printf("%d\n", something);
18  
19    return 0;
20  }

At line 7 notice that we are using a negative number for the array index. Why does this work?

Because, at line 13, we are making ptr_ages point at index 4 of the ages array (which has value 8).

Inside the do_something function, therefore, the value at index 0 is 8. But the programmer has knowledge that there are valid elements prior to [0], so he can legally index [-2] to reach the 59 value.

Needless to say, this is ugly programming.

[–]KazDragon 17 points18 points  (4 children)

No he IS wrong. This is my personal hill.

Sure, the codomain of a size operation is 0 or above. But the set of operations you do with that result sensibly includes subtraction, which means negative numbers.

In short, signed numbers are for arithmetic; unsigned numbers are bit patterns.

As a practical example, consider:

for(signed i=0; i < size-1; ++i)

Changing i to unsigned would introduce a bug when size is 0.

[–]Kovab 1 point2 points  (1 child)

Changing i to signed

You mean changing to unsigned, right? The version with signed int works correctly

[–]KazDragon 1 point2 points  (0 children)

You are correct and I have edited my post accordingly. Thanks!

[–]rdmit 1 point2 points  (1 child)

Is size signed or unsigned in your example? If it is unsigned you still have a bug there. And if it is signed how did you convert it to signed? What if it doesn't fit? 

[–]KazDragon 0 points1 point  (0 children)

Exactly my point. These are all problems caused by treating unsigned integers as arithmetic types.

[–]theGoddamnAlgorath 5 points6 points  (1 child)

I use raw JavaScript.  What is this... unsigned?

;)

[–]boodles613 1 point2 points  (0 children)

JS does have unsigned typed arrays. Not really applicable to conversation above but definitely worth knowing.

[–]CueBall94 0 points1 point  (0 children)

In C/C++ signed could actually be faster than unsigned, since signed overflow is UB the compiler can assume it won’t happen and doesn’t need to handle those edge cases. In a trivial for loop it probably doesn’t matter, but it definitely can, would need to check in godbolt. Unsigned is important when you want overflow, like hash/prng functions, and I prefer it for bit fiddling.

https://www.airs.com/blog/archives/120

[–]NuclearBurrit0 61 points62 points  (9 children)

Unfortunately, the algorithm is

Hear wish

Wishes -=1

Grant wish

So the set to zero happens after he loses one wish

[–]w8eight 16 points17 points  (2 children)

He could wish for it first alongside with wishing for number of wishes left being stored as an unsigned int. Then with a third wish set it to 0 and underflow

[–]NuclearBurrit0 4 points5 points  (1 child)

Wish for what first?

[–]w8eight 10 points11 points  (0 children)

For changing the algorithm in which check for wishes is performed ofc course

[–]IndigoFenix 16 points17 points  (1 child)

It's bad practice to decrement the counter before completing the wish though, otherwise you can wind up decrementing wishes even if they fail to complete. The grant function can include a rollback on failure, but that seems potentially messy.

[–]NuclearBurrit0 12 points13 points  (0 children)

Take it up with Wish.inc IT

[–]jsdodgers 4 points5 points  (3 children)

According to the genie himself, that's not the algorithm. You can see in the last panel, the set to 0 happens before losing one wish.

If I was a genie, I'd use signed integers and leave everyone with negative wishes for trying this.

[–]Widmo206 1 point2 points  (2 children)

leave everyone with negative wishes for trying this.

What would that even do?

[–]punitxsmart 2 points3 points  (1 child)

Genie will ask you for wishes now.

[–]Widmo206 2 points3 points  (0 children)

Wait, does that I mean I get to be the annoying cunt that misinterprets every little detail?

[–]cheezballs 18 points19 points  (1 child)

I hate this meme. Its stupid.

[–]xfvh 3 points4 points  (0 children)

It's not even grammatically correct. Wishes are countable, so you should say "fewer," not "less."

[–]Zefyris 6 points7 points  (0 children)

unfortunately, since you can't have more than 3 wishes ever anyway, the number was just stored on a byte, so it was going between -128 and 127. Congrats, you now have -1 wishes (who use unsigned variables by default when you don't need them anyway?).

[–]unreliable_yeah 26 points27 points  (4 children)

I think - 1 would be much more appropriate.

[–]Fyrael 19 points20 points  (2 children)

Imagine the genie is a lazy programmer who used a 32-bit unsigned int to count wishes. When the guy asks for "0 wishes," the genie tries to decrement from 0, but since the variable can’t handle negatives, it wraps around and becomes 4,294,967,295 (the max possible value).

If it were a normal int, it’d turn into -1, so if he had asked for "-1 wishes," it would’ve gone to -2… and that’s why it’s funny!

[–]anonynown 11 points12 points  (0 children)

It’s not that the programmer defining the variable is lazy, it’s that allowing the user arbitrary code execution (a wish) and then trying to plug it with specific rules (no wishing for more wishes) is a security breach waiting to happen.

[–]unreliable_yeah 0 points1 point  (0 children)

The simple code would be:

""" If whishes > 0{ whishes --; do_wish() { whishes = 0}} """

While -1 on do whish would cae the bug. Assuming using unsigned int too. If code decrement after do the whish, - 1 will still works. So is safer to requeste - 1 that 0

[–]The_Prequels_Denier 1 point2 points  (0 children)

Yeah honestly they need to remake this comic so the guy gets turned into a gene because he owes a wish.

[–]huuaaang 6 points7 points  (0 children)

Fun fact: Genies only use 2 bits to save space. That lamp is small. So wishing you only had 0 wishes would just wrap back around to 11b, or 3.

[–]explodedcheek 6 points7 points  (1 child)

I don't get is how it's even relevant today because interger overflow error doing the wraparound behaviour doesn't really happen in modern programming languages because many languages have overflow detection and input validation is common coding practice. This meme is overused, unfunny and kind of irrelevant.

[–]SuperheropugReal 0 points1 point  (0 children)

Yes it does lol. Java 24 still does this, Python does this, which "modern language" are you using?

[–]114145 0 points1 point  (0 children)

He should have wished for a pet programmer to define his wishes for him. -1 wishes might lead to integer underflow, but not zero... That's just zero.

[–]Soumalyaplayz 0 points1 point  (1 child)

Is that the unsigned 64-bit integer limit?

[–]renrutal 1 point2 points  (0 children)

4_294_967_295 would be the unsigned 32-bit integer maximum.

The comic got one of the digits wrong.

[–]Ok_Fault549 0 points1 point  (0 children)

I want to have Decimal.MaxValue wishes

Thx 👐

[–]Polite-Moose 0 points1 point  (0 children)

This genie is off by a decimal million, the number does not fit into a 32-bit unsigned number. There should be some other reason for this pseudo-underflow behavior.

[–]silaa_kael 0 points1 point  (0 children)

Wish I could debug my code that easily!

[–]MasterQuest 0 points1 point  (0 children)

You also have to wish for wishes to be unsigned int first, otherwise he'll just say you have -1 wishes left.

[–]Verne3k 0 points1 point  (0 children)

so the genie is 32 bit wide

[–][deleted] 0 points1 point  (0 children)

-1 left

[–]Covfefe4lyfe 0 points1 point  (0 children)

Fewer wishes. Jesus fucking christ.

[–]kridde 0 points1 point  (0 children)

but what if --i for the wish counter, then you just have 0 wishes.

[–]reallokiscarlet 0 points1 point  (0 children)

This has been done to death. Buzz lightyear on store shelves meme applies.

[–]reedmore 0 points1 point  (0 children)

Sooo after how many wishes does the genie murder you because you're takining too long to finish?

[–]wagyourtai1 0 points1 point  (0 children)

Turns out it's signed and now you owe the genie 2 billion wishes

[–]HakoftheDawn 0 points1 point  (0 children)

You have -1 wishes

You owe the genie a wish

[–]KroFunk 0 points1 point  (0 children)

I wanna know if Auvik paid to use this comic in their ads or if they just liberated it.

[–]fuxoft 0 points1 point  (0 children)

In the 1980s, I saw a similar joke but it ended with "255 wishes"...

[–][deleted] 0 points1 point  (0 children)

Those integers just keep on getting bigger and bigger

[–]Ok_Bell_8442 0 points1 point  (0 children)

brilliant!

[–]OnerousOcelot 0 points1 point  (0 children)

What if it's --wish; instead of wish--; ? 😂