5 ms·
You'd have to care about the difference between indexing with a literal and indexing with variables of different types/widths, and how indexing with a variable
by philsnow 4y ago
You'd have to care about the difference between indexing with a literal and indexing with variables of different types/widths, and how indexing with a variable interacts with the size of the area.
For instance if you have an int array that contains the numbers 1-250 and you index with a uint8 variable i,
for (uint8 i = 247; i++;) {
// print circ_arr[i]
}
for the values of i near the overflow points of the circular array and of the uint8 it gets weird:
i circ_arr[i]
247 247
248 248
249 249
250 250
251 1 # 251 % 250 = 0
252 2 # 252 % 250 = 1
253 3 # ...
254 4
255 5
0 1 # i overflows to 0
1 2
...
- feoren 4y agoRight, the calling code needs to handle its own integer overflows, of course. And if your circular array has a size other than a power of 2 you can get only a partial enumeration in the cycle that includes overflow. Sure. But are you really indexing an array of unknown size with a uint8? It's really impossible that there might be more than 255 things you ever care about? No. Everyone who is using a uint8 to index arrays is either doing something extremely low-level and fiddly where abstractions like this simply don't apply, or they're idiots who are doing cargo-cult shotgun "optimization" because they don't know how to write code that works. If you're indexing with a [u]int32 you need to worry about this once every 4 billion increments, and if an incomplete cycle is a show-stopper for you, you can compute a safe modulo yourself based on the size(s) of your circular array(s), but more likely you just need something else. But really, you don't care if your cache hiccups a little once every 4 billion caches. You make a good point, of course, I'm just allergic to people poking holes in back-of-the-napkin explanations of things with the trite "but integers can overflow!" It's one of those most common well actuallys written on this site. Of course integers can overflow. They almost never do though, do they? And if they do, a test fails and you add a single line somewhere to fix it. I really think the vast majority of programmers are too often thinking about bits when they should be thinking about math.
- ablob 4y agoThe point made is independent of the integer size and I think we should assume in good faith, that uint8 was chosen for the purposes of an example.
- feoren 4y agoUm, maybe, but then his example is sixteen million times worse than reality! If I argued against some technology by showing how bad it would be if it were sixteen million times worse, that's just not a very good argument, is it?
- ablob 4y agoWhy is an overflow that is generated by the caller your concern?
- Someone 4y agoIn a language where arrays are fixed-size, I think the proper solution is to have arrays not indexed by integers, but by a custom modular type that depends on the array with values in [0,n) that allows literals in the range [-n, n-1], with literal ‘-1’ being a different way to write ‘n-1’, etc. You’d need a way to get that type, for example as float a[10,20] // two-dimensional array of floats typeof(a.dims(0)) i = 0 // modular type with values in [0,9] typeof(a.dims(1)) j = 0 // modular type with values in [0,19] or, slightly neater: auto i = a.indextype(0) auto j = a.indextype(1) Ugly syntax, but in a modern language, most code would probably do something like for (i,j,value) in a where the types are inferred. Having those modular types means the compiler would do the arithmetic correct for the array, while the negative literals allow programmers to specify “last” and “next to last” correctly.