C ++ to C #: указатели и массивы - PullRequest
2 голосов
/ 28 ноября 2010

Ниже приведена процедура консольного приложения Win32, которая демонстрирует зависимость различных указателей от массива. Изменение значений в исходном массиве (модели), например, раскомментирование строк, помеченных «// uncomment ...», приводит к изменению вывода. Мой вопрос заключается в том, как мне получить или имитировать это поведение в среде управляемого кода C # (т.е. без использования небезопасных и указателей)?

#include "stdafx.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    float model[100];
    for(int i = 0; i < 100; i++) { model[i] = i; }

    // uncomment these to alter the results
    //model[5] = 5000;
    //model[20] = 20000;
    //model[38] = 38000;

    static const int componentCount = 5;

    float* coefs = model;                   // coefs points to model[0]
    float* mean = coefs + componentCount;   // mean points to model[0 + componentCount] == model[5]
    float* cov = mean + 3*componentCount;   // cov points to model[0 + componentCount + 3*componentCount] == model[20] 

    int ci = 2;
    float* c = cov + 9*ci;  // c points to model[0 + componentCount + 3*componentCount + 9*ci] == model[38] 

    int i = 0;
    cout <<"model : "<< model[i] << endl;   // 0
    cout <<"coefs : "<< coefs[i] << endl;   // 0
    cout <<"mean  : "<< mean[i] << endl;    // 5 (or 5000)
    cout <<"cov   : "<< cov[i] << endl;     // 20 (or 20000)
    cout <<"ci    : "<< ci << endl;         // 2
    cout <<"c     : "<< c[i] << endl;       // 38 (or 38000)

cin.get(); }

Ответы [ 3 ]

14 голосов
/ 28 ноября 2010

Вы можете сделать то же самое в C # без небезопасного кода:

struct ArrayPointer<T>
{
    private T[] array;
    private int offset;
    public ArrayPointer(T[] array) : this(array, 0)
    {
    }
    private ArrayPointer(T[] array, int offset)
    {
        Debug.Assert(array != null);
        Debug.Assert(offset >= 0);
        Debug.Assert(offset < array.Length);
        this.array = array;
        this.offset = offset;
    }
    public static ArrayPointer<T> operator+(ArrayPointer<T> p1, int p2)
    {
        return new ArrayPointer<T>(p1.array, p1.offset + p2);
    }

И так далее.Определите операторы для сложения, вычитания, увеличения, уменьшения, сравнения, индексации, преобразования из массивов и так далее.Тогда вы можете сказать:

int[] arr = whatever;
ArrayPointer<int> pointer = arr;
pointer+=2;
pointer--;
int x = pointer[3];

и т. Д.

Этот подход имеет много приятных свойств.Например, вы можете сделать отладочное утверждение, если вы когда-либо сравниваете p1> p2, когда p1 и p2 являются указателями на внутренности различных массивов.Это почти всегда ошибка в C, но ее трудно поймать.

4 голосов
/ 28 ноября 2010

Вы можете написать класс, представляющий массив с некоторым смещением, аналогичным приведенному ниже. Кроме того, вы можете захотеть реализовать ICollection<T> или хотя бы IEnumerable<T>.

class ArrayWithOffset<T>
{
  T[] m_array;
  int m_offset;

  public ArrayWithOffset(T[] array, int offset)
  {
    m_array = array;
    m_offset = offset;
  }

  public T this[int i]
  {
    return m_array[offset + i]
  }
}
0 голосов
/ 28 ноября 2010

Вместо одного параметра, указателя на элемент массива, используйте пару параметров (массив, смещение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...