EagerToLearn
EagerToLearn

Reputation: 675

Integer overflow to negative number

According to this link, I learned that in IE8 the the new element's index will be a negative number if the array was created with an index greater than 2147483647.

And there is this sample :

function test() { 
    var arr = new Array();         
    arr[2147483650] = 10000; 
    arr.push(10);     
    document.write(arr["-2147483645"] == 10); 
} 
test();

What I don't understand is, how come the newly added element of the array have the index of -2147483645, I understand the negative part, I just don't know how to know that the new index is 2147483645, not -2147483644 or -2147483651 ...

Upvotes: 6

Views: 7310

Answers (2)

Nick Zuber
Nick Zuber

Reputation: 5637

In your example, I want to point out that an index of -2147483645 is not created, rather, your array is converted to an object:

function test() { 
    var arr = new Array();         
    arr[2147483650] = 10000; 
    arr.push(10);     
    console.log(arr["-2147483645"] == 10); 
    console.log(arr)
} 
test();

// false
// [2147483650: 10000, 2147483651: 10]

What I don't understand is, how come the newly added element of the array have the index of -2147483645

It's important to note that everything in JavaScript is an object under the hood. With that being said, even an Array is really just an object. In this case, your array doesn't really have an index of -2147483645, in fact, no integer overflow actually occurs. Rather your overflowed integer is converted to a string and becomes a key that maps to a value within your array object.

var arr = [];
arr[2147483650] = 'foo';

// The index is really just converted to a string behind the scenes
console.log(arr[2147483650] === arr["2147483650"]);

// true

If you try to index an array with an integer that is out of range, it will assume that you're creating an object and create an object instead of indexing your array.

var arr = [];
arr[0] = 'foo';
console.log(arr);
// ["foo"]
// Has the array notation

var arr = [];
arr[2147483650] = 'bar';
console.log(arr);
// [2147483650: "bar"]
// Notice the object notation?

Upvotes: 4

Matthew
Matthew

Reputation: 7590

When representing a number in 32 bits, the highest bit is used as a sign bit, so when representing a number like 2147483647 in binary, it is

01111...111

where there are 31 1's. When we add one more to that, we get

10000...000

where there are 31 0's. Thus we have tripped the sign bit to be one indicating a negative number. However, because of a need to avoid representing 0 twice, we wrap the number, so instead of representing -0, this represents negative 2147483648 (not 2147483647 because the positive side needed to represent 0, but as the negative side doesn't, we get one "extra" negative number).

Each time that we add one to this, it will increase the binary representation, which counts down through the negative numbers

1000...00 = -2147483648 // this is 2147483648
1000...01 = -2147483647 // this is 2147483649
1000...10 = -2147483646 // this is 2147483650

and so on. Thus 2147483650 gets wrapped to -2147483646 and therefore, one more than that gets set to -2147483645.

See here for more detail.

Upvotes: 6

Related Questions