Переписываю код с Си на C#. Столкнулся со следующей проблемой.
Вот код на си.
int right[2 * par - 1];
int left[2 * par - 1];
...
void func()
{
int *p;
// some code
if (k & mask)
p = &right[*p];
else
p = &left[*p];
}
А вот мой вариант на C#.
int[] right = new int[2 * par - 1];
int[] right = new int[2 * par - 1];
...
unsafe void func()
{
int *p;
//some code
if ((k & mask) != 0)
p = &right[*p];
else
p = &left[*p];
}
В if VS выдаёт следующую ошибку
Адрес нефиксированного выражения можно получить только внутри инициализатора оператора fixed
Пока не понимаю, как решить проблему, используя этот оператор. Помогите разобраться, пожалуйста.
P.S.
используя оператор fixed
, как показано в примере из msdn, ничего не получилось, поскольку в том примере необходимо в круглых скобках писать конструкцию типа int *p = &variable
, а у меня уже в начале кода идёт объявление int *p
, и в процессе работы оно успешно присваивается и изменяется, но вот доходя до if
, вылетает ошибка.
Переписывать подобный код на C# "в лоб" - не лучшая идея.
Фактически, в этом коде указатель p
используется для обозначения сразу массива и его элемента. И раз уж язык C# не дает так делать - можно вернуться к полной форме:
int[] parray;
int[] pindex;
//some code
if ((k & mask) != 0)
{
int v = parray[pindex]; // Ранее *p
parray = right;
pindex = v;
}
else
{
int v = parray[pindex]; // Ранее *p
parray = left;
pindex = v;
}
Если подобного кода много - можно завести себе в помощь структуру, которая будет себя вести аналогично указателю на ячейку массива:
struct ArrayCell<T>
{
private readonly T[] array;
private readonly int index;
public ArrayCell(T[] array, int index)
{
this.array = array;
this.index = index;
}
public T Value
{
get { return array[index]; }
set { array[index] = value; }
}
}
static class ArrayCellExtensions
{
public static ArrayCell<T> Cell<T>(this T[] array, int index) => new ArrayCell<T>(array, index); // Немного сахара
}
// ...
ArrayCell<int> p;
//some code
if ((k & mask) != 0)
p = right.Cell(p.Value);
else
p = left.Cell(p.Value);
Здесь два варианта, если массивы создаются и живут внутри функции, и их размер небольшой то можно их выделить на стеке:
int* right = stackalloc int[2 * par - 1];
...
if ((k & mask) != 0)
p = &right[*p];
В вашем случае это не ок, потому что размер массива у вас переменный, можно нарваться на StackOverflow ); Вариант два, зафиксировать расположение в памяти:
fixed (int* _right = &right[0], _left = &left[0])
{
...
if ((k & mask) != 0)
p = &_right[*p];
}
Работать с укзателями на массив, можно только внутри блока фиксед. Можно схитрить и написать как-нибудь:
if ((k & mask) != 0)
fixed(int* ptr = &right[*p]) { p = ptr; }
но первая же сборка мусора, может переместить данные куда угодно и указатель соответственно станет не валиден.
p.s. у вас проблема не в присваивании p и не в if, а в попытке взять адрес массива который не закреплен в памяти.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Прошу помощи найти инструмент для лова запросов ReacJS Уже замучился весь инет обрыскал не нашел ответа, как отследить запросы ReactJS
Походу не один я столкнулся с такой проблемой, но ответ в гугле найти не могуВообщем суть такая, сохраняю я код скрипта js, нажимаю f5 и f12->sources,...
Здравствуйте, такая задача: нужно написать функцию, которая будет выводить измененную строку, а именно если мы получаем строку 'foo' -> 'foo1', 'foo000'...