Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Last active December 24, 2025 22:41
Show Gist options
  • Select an option

  • Save sunmeat/d53abc35c4667538c3db558180842d32 to your computer and use it in GitHub Desktop.

Select an option

Save sunmeat/d53abc35c4667538c3db558180842d32 to your computer and use it in GitHub Desktop.
fixed example
using System.Runtime.InteropServices;
using System.Text;
class Cat
{
public int paws = 4;
// якщо зробити властивість, то не вдасться застосувати оператор &
}
class CopyMaker
{
// ключове слово unsafe дозволяє використовувати вказівники всередині методу
public static unsafe void Copy(byte[] src, int srcIndex, byte[] dst, int dstIndex, int count)
{
if (src == null || srcIndex < 0 ||
dst == null || dstIndex < 0 || count < 0)
{
throw new ArgumentException(); // перевірка на коректність параметрів
}
int srcLen = src.Length;
int dstLen = dst.Length;
if (srcLen - srcIndex < count ||
dstLen - dstIndex < count)
{
throw new ArgumentException(); // перевірка на розмір даних
}
// оператор fixed "прикріплює" вказівники на масиви src і dst
// щоб збирач сміття не переміщав їх у пам’яті
fixed (byte* pSrc = src, pDst = dst)
{
byte* ps = pSrc; // вказівник на вихідний масив
byte* pd = pDst; // вказівник на цільовий масив
// цикл копіювання по 4 байти за раз
for (int n = 0; n < count / 4; n++)
{
*((int*)pd) = *((int*)ps); // копіюємо по 4 байти (ціле число)
pd += 4; // зсуваємо вказівник на 4 байти
ps += 4; // зсуваємо вказівник на 4 байти
}
// завершення копіювання залишкових байтів, якщо їх менше 4
for (int n = 0; n < count % 4; n++)
{
*pd = *ps; // копіюємо по 1 байту
pd++;
ps++;
}
}
}
}
class FileReader
{
const uint GENERIC_READ = 0x80000000; // прапорець для читання
const uint OPEN_EXISTING = 3; // прапор для відкриття існуючого файлу
IntPtr handle; // дескриптор файлу
// метод для створення файлу (або відкриття існуючого)
[DllImport("kernel32", SetLastError = true)]
static extern unsafe IntPtr CreateFile(
string FileName, // ім’я файлу
uint DesiredAccess, // режим доступу
uint ShareMode, // режим спільного доступу
uint SecurityAttributes, // атрибути безпеки
uint CreationDisposition, // як створювати файл
uint FlagsAndAttributes, // атрибути файлу
int hTemplateFile // дескриптор шаблонного файлу
);
// метод для читання файлу
[DllImport("kernel32", SetLastError = true)]
static extern unsafe bool ReadFile(
IntPtr hFile, // дескриптор файлу
void* pBuffer, // буфер для даних
int NumberOfBytesToRead, // кількість байтів для читання
int* pNumberOfBytesRead, // кількість фактично прочитаних байтів
int Overlapped // буфер для асинхронного читання
);
// метод для закриття файлу
[DllImport("kernel32", SetLastError = true)]
static extern unsafe bool CloseHandle(
IntPtr hObject // дескриптор об’єкта
);
// метод для відкриття файлу
public bool Open(string FileName)
{
// відкриваємо існуючий файл для читання
handle = CreateFile(
FileName,
GENERIC_READ,
0,
0,
OPEN_EXISTING,
0,
0);
if (handle != IntPtr.Zero)
return true;
else
return false;
}
// метод для читання даних із файлу
public unsafe int Read(byte[] buffer, int index, int count)
{
int n = 0;
// !!! FIXED !!!
fixed (byte* p = buffer)
{
if (!ReadFile(handle, p + index, count, &n, 0))
return 0; // якщо читання не вдалося, повертаємо 0
}
return n; // повертаємо кількість прочитаних байтів
}
// метод для закриття файлу
public bool Close()
{
// закриваємо дескриптор файлу
return CloseHandle(handle);
}
}
class Program
{
// метод для зміни значення за вказівником
unsafe static void SetIntegerValue(int* x)
{
Console.WriteLine("Розіменування вказівника для зміни cat.paws...");
*x = 5; // змінюємо значення за вказівником
}
unsafe static void Main()
{
Console.OutputEncoding = Encoding.UTF8;
var cat = new Cat();
Console.WriteLine("cat.paws ініціалізовано значенням {0}", cat.paws); // виводимо початкове значення 4
// оператор fixed фіксує об’єкт cat у межах
// включаючого його оператора, щоб збирач сміття не перемістив його
fixed (int* ptr = &cat.paws)
{
Console.WriteLine("Виклик SetIntegerValue із передачею вказівника на cat.paws");
SetIntegerValue(ptr); // передаємо вказівник на paws методу
}
// переконуємося, що компонент через вказівник змінився
Console.WriteLine("Після повернення з SetIntegerValue, cat.paws = {0}", cat.paws);
//////////////////////////////////////////////////////////////////////////////////////
var a = new byte[100];
var b = new byte[100];
// заповнюємо масив a значеннями від 0 до 99
for (int i = 0; i < 100; ++i)
a[i] = (byte)i;
// викликаємо метод копіювання
CopyMaker.Copy(a, 0, b, 0, 100);
// виводимо перші 10 елементів масиву b
Console.WriteLine("Перші 10 елементів:");
for (int i = 0; i < 10; ++i)
Console.Write(b[i] + " ");
Console.WriteLine("\n");
//////////////////////////////////////////////////////////////////////////////////////
string path = "1.txt";
var buffer = new byte[128];
var fr = new FileReader();
if (File.Exists(path))
{
fr.Open(path);
// припускаємо, що файл у форматі ASCII
var Encoding = new ASCIIEncoding();
int bytesRead;
do
{
bytesRead = fr.Read(buffer, 0, buffer.Length); // читаємо дані
string content = Encoding.GetString(buffer, 0, bytesRead); // перетворюємо в рядок
Console.Write("{0}", content); // виводимо дані
}
while (bytesRead > 0);
fr.Close(); // закриваємо файл
}
else
{
Console.WriteLine("Не вдалося відкрити запитаний файл");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment