Здравствуйте, Egor, Вы писали:
E>Ну вообщем наваял что-то на уровне интуиции.
E>Вроде бы работает, хотя есть вопросы.
E>Например, при выделении памяти под буфер
E>E>buf = new(char[sbuf])
E>
E>Почему он не пустой. В нем сразу есть какой-то мусор.
Оператор new всего-лишь выделяет свободный (т.е. не занятый другими программами) участок памяти под твою программу и возвращает его адрес в памяти. Он не заполняет его нулями. То, что ты называешь мусором на самом деле есть отрывок неких данных, которые уже никому не нужны (возможно, другая программа завершилась и этот участок памяти стал свободным). Если тебе надо заполнить этот участок нулями, используй функцию memset(buff, 0, num_bytes). Или выделяй память функцией calloc — она заполняет нулями сразу.
E>E>sbuf = (atoi(_argv[2]))*1024;
E>
E>то переменная равна нулю. Приходится делать вот так
E>E>sbuf = (atoi(_argv[2]));
E>sbuf *= 1024;
E>
На самом деле так и должно быть. Попробую объяснить: переменная sbuf имеет тип long (4 байта), а функция atoi возвращает тип int (2 байта). Происходит следующее: компилятор видит, что перемножаются 2 числа типа int, и, соответственно, перемножает их как int'ы и результат тоже будет int. Перемножив 64*1024 получим число 65536, которое в двоичной записи имеет вид:
00000000 00000001 00000000 00000000 разряды
4 3 2 1 байты
В промежуточный результат будет записан 0 (первые два байта — размер int). И только потом произойдет приведение типов, и эти два байта станут четырьмя. Типы приводятся так: если от знакового к знаковому, то недостающие два байта заполняются последним (знаковым) битом. В остальных же случаях, недостающие байты заполняются нулями. При приведении от большего по диапазону к меньшему лишние старшие байты просто тупо обрезаются.
char => int
11111110 bin = -2 dec => 11111111 11111110 bin = -2 dec знаковый бит = 1
01111111 bin = 127 dec => 00000000 01111111 bin = 127 dec знаковый бит = 0
char => unsigned int
11111110 bin = -2 dec => 00000000 11111110 bin = 254 dec заполняем нулями
01111111 bin = 127 dec => 00000000 01111111 bin = 127 dec заполняем нулями
int => char
00000001 00000000 bin = 128 dec => 00000000 bin = 0 dec
11111111 00000001 bin = -255 dec => 00000001 bin = 1 dec
11111111 10000001 bin = -127 dec => 10000001 bin = -127 dec
long => unsigned int
00000000 00000001 00000000 00000000 bin = 65536(64Kb) dec => 00000000 00000000 bin = 0 dec
Значит, чтобы правильно перемножить два числа, надо сделать приведение типов до того как произойдет перемножение:
sbuf = (long)atoi(_argv[2])*1024;
// Заметь, что приведение типа имеет больший приоритет, чем умножение. Т.е. это эквивалентно следующему:
sbuf = ( (long)atoi(_argv[2]) )*1024;
Тогда числа будут перемножаться как long и промежуточный результат будет тоже long. Ты в общем так и сделал, но только двумя строками кода, вместо одной.
E>Скажите, а вот эти две строки не одинаково ли будут работать?
E>fread(buf, 1024, 64, f);
E>fread(buf, 1024*64, 1, f);
Они будут одинаково работать только в случае, если 1024*64 не вылезает за пределы диапазона unsigned int, а он вылеает (смотри пример выше). Поэтому 1024*64 на самом деле будет равно нулю... Значит надо использовать fread(buf, 1024, 64, f); но тут надо учесть, что читать он будет блоками по 1 килобайту и, если в конце файла будет, скажем 1023 байта, то он их не считает. Необходимо будет в самом конце после цикла сделать вызов fread(buf, 1, 1023, f); и обработать эти байты отдельно.
Эта же проблема стоит и при выделении памяти: ты фактически выделяешь 0 байт и твоя программа однажды может громко вывалиться с эксепшеном. Странно, что он вообще выделяет блок памяти размером 0 байтов...

Таким способом ты можешь выделить максимум 65535 байт, что на один байт меньше нужных тебе 64Кб. Еще можно попробовать функцию calloc(64, 1024). Если не поможет, то тогда уже farmalloc — эта точно сработает, но с такой памятью необходимо "особенное" обращение