2015-10-26 4 views
-1

Я столкнулся с причудливой ошибкой при установке позиции в FileStream: «Требуется неотрицательное число. Имя параметра: значение».Преобразование в тип int дает отрицательное число

public string this[Int64 index] 
{ 
    get 
    { 
     Byte n = Convert.ToByte(0); 
     Byte[] Buffer = new Byte[255]; 
     mem.Position = (int)(index * 256); //Error occurs here 
     mem.Read(Buffer, 0, Buffer.Length); 
     Buffer = (from b in Buffer where b != n select b).ToArray(); 
     return System.Text.Encoding.Default.GetString(Buffer); 
    } 
    set 
    { 
     mem.Position = (int)(index * 256); 
     value += String.Concat(Enumerable.Repeat("\0", 255 - value.Length)); 
     Byte[] Buffer = System.Text.Encoding.Default.GetBytes(value + "|"); 
     mem.Write(Buffer, 0, Buffer.Length); 
    } 
} 

Как долго, индекс имеет значение 8,388,608 как и ожидалось (индекс * 256) = 2147483648, но когда я преобразовать его в междунар, я получаю такое же количество, только отрицательное. (-2147483648). Почему это происходит?

Целевая структура .NET 4 и приложение построено для «Любой процессор».

фон

В случае кто-то интересно о цели этого кода, он является частью класса, я написал, что подражает строковые массивы, но без сохранения значений в памяти. Класс MappedStringArray позволяет мне работать с файлами практически любого размера, не нарушая ограничений по ОЗУ, поскольку он знает только расположение строк в файле и считывает их по мере необходимости.

ответ

6

Это целочисленное переполнение. Значение 2 147 483 648 не может быть представлено int, макс. положительное значение 2^31-1 = 2,147,483,647. (Это, в свою очередь, потому, что int является 4-байтовым = 32-битным значением в C#, а поскольку он является подписанным int, самый первый бит указывает знак, оставляя 31 бит для фактического числа).

Вы можете видеть, что 2147483648 именно 1 больше, чем это, и поэтому int будет переполнение, установить первый бит в 1, что указывает на отрицательный знак, а остальное время нули, и как таковой, вы получите самый большой отрицательное число возможно для int.

+0

Спасибо. По-видимому, свойство position длинное, поэтому я выбрал преобразование типа, потому что он не нужен. Однако, хорошо знать, что это произойдет в будущем. Я бы подумал, что если максимальный размер был превышен, то попытка преобразования типа вызовет ошибку. Если вы спросите меня, это немного глупо, что он превратит его в отрицательное число. Я имею в виду, что делать, если я делаю расчет? Это действительно запустило бы ключ. –

+5

Но это что-то, что * * должно произойти на компьютере. «Обращение к самому отрицательному числу» связано с фиксированным форматом ваших данных ('int' =' int32' = 1 знаковый бит, 31 бит данных) и представление отрицательных и положительных значений по усмотрению двух. Вы можете прочитать это по адресу https://en.wikipedia.org/wiki/Two's_complement#Most_negative_number. –

+2

@JoshuaDannemann Вы можете включить проверенную арифметику в свойствах проекта, и это заставит ее генерировать исключение во всех переполнениях, которые не происходят внутри блока «unchecked». – Kyle

-2

поскольку 2,147,483,648 - это гексагон x80000000. Это отрицательное число в отношении int32

+0

@ pm100 В этом контексте может помочь какой-то контекст, поскольку, я думаю, OP не знает, что означает 'x80000000', или почему' int32' считает переполнение отрицательным. [Ответ Maximilian] (http://stackoverflow.com/a/33352026/1454048), кажется, лучше всего отвечает, почему переполнение работает таким образом и затрагивает специфику исходного вопроса OP. – admdrew

-2

INT - знаковое значение. Используйте ULONG в коде вместо INT.

mem.Position = (Ulong)(index * 256); 
Смежные вопросы