Re[7]: Массив и указатель: преобразование
От: Кодт Россия  
Дата: 17.09.10 09:56
Оценка:
Здравствуйте, Tscheineg, Вы писали:

T>Но меня ждал еще один сюрприз: MSVC все равно не сообщает об ошибке, так что вся эта затея обломилась. Как-то можно заставить компилятор замечать такие явные ошибки?


Есть смысл отказаться от голого сишного массива char(&)[N] в пользу полноценного типа boost::array<char,N> или чего-то в таком роде.
Тогда можно заставить ошибки ловиться в рантайме.
template<class T>
class proxy_array
{
  T* arr_;
  size_t n_;
public:
  proxy_array(T* arr, size_t n) : arr_(arr), n_(n) {}

  T& operator[](int i) const { assert(i>=0 && i<n_); return arr_[i]; }
                               /////////////////////
  T* data() const { return arr_; }
  size_t size() const { return n_; }

  // при желании - можно прикрутить итераторы с отладочными средствами
};

TData Parse(proxy_array<char> Buf)
{
  int i=0;
  char c0 = Buf[i++];
  char c1 = Buf[i++];
  ....
  char c5 = Buf[i++]; // assertion fault!
  ....
}

TData Read(char* Msg, int Len)
{
  return Parse(proxy_array<char>(Msg,Len));
}


T>Еще обнаружил, что если строку #2 слегка изменить:

T>
const TBufArr &BufArr=reinterpret_cast<const TBufArr&>(Msg+1);

T>то возникает ошибка error C2102: '&' requires l-value
T>В чем тут дело?

Дело в том, что реинтерпрет ссылки — это попытка трактовать переменную, а не её значение.
Msg+1 — это значение типа char*, существующее только мысленно.
Msg[1] — это переменная типа char, находящаяся по адресу Msg+1
Вот (ссылку на) эту переменную (плюс следующие за ней несколько байтов) уже можно трактовать как (ссылку на) переменную иного типа.
А (указатель на) — можно трактовать как (указатель на).

То есть
const TBufArr* pBuf =  reinterpret_cast<const TBufArr*>(  Msg+1  );
const TBufArr& rBuf = *pBuf // или, что то же самое,
                      *reinterpret_cast<const TBufArr*>(  Msg+1  )
                       reinterpret_cast<const TBufArr&>(*(Msg+1) )
                       reinterpret_cast<const TBufArr&>(  Msg[1] )
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.