Я пишу заявку, и мне нужно было сделать несколько арифметических указателей. Однако это приложение будет работать на другой архитектуре! Я не был уверен, если это будет проблематично, но после прочтения Эта статья, Я думал, что я должен изменить это.
Вот мой оригинальный код, который мне не очень понравился:
class Frame{
/* ... */
protected:
const u_char* const m_pLayerHeader; // Where header of this layer starts
int m_iHeaderLength; // Length of the header of this layer
int m_iFrameLength; // Header + payloads length
};
/**
* Get the pointer to the payload of the current layer
* @return A pointer to the payload of the current layer
*/
const u_char* Frame::getPayload() const
{
// FIXME : Pointer arithmetic, portability!
return m_pLayerHeader + m_iHeaderLength;
}
Довольно плохо, не правда ли! Добавление int
значение для u_char
указатель! Но потом я изменился на это:
const u_char* Frame::getPayload() const
{
return &m_pLayerHeader[m_iHeaderLength];
}
Я думаю, теперь компилятор может сказать, сколько прыгать! Правильно? Является ли операция []
на массиве рассматривается как указатель арифметики? Устраняет ли это проблему переносимости?
p + i
а также &p[i]
синонимы, когда p
это указатель и i
значение целочисленного типа. Так много, что вы даже можете написать &i[p]
и это все еще действует (так же, как вы можете написать i + p
).
Проблема переносимости в примере, на который вы ссылаетесь, исходила sizeof(int)
варьируется на разных платформах. Ваш код просто отлично, если m_iHeaderLength
это число u_char
Вы хотите пропустить.
В вашем коде вы продвигаете m_pLayerHeader на m_iHeaderLength u_chars. Пока все написанные данные имеют одинаковый размер для u_char, а i_HeaderLength — это число u_chars в области заголовка, которое вы в безопасности.
Но если m_iHeaderLength
действительно ссылается на байты, а не на u_chars, тогда у вас могут возникнуть проблемы, если m_iHeaderLength
Предполагается, что указатель опережает другие типы, кроме char.
Скажем, вы отправляете данные из 16-битной системы в 32-битную систему, область заголовка определяется следующим образом
struct Header {
int something;
int somethingElse;
};
Предположим, что это только часть общего сообщения, определенного структурой Frame.
На 32-битной машине вы записываете данные в порт, с которого 16-битная машина будет читать.
port->write(myPacket, sizeof(Frame));
На 16-битной машине у вас такое же определение заголовка, и вы пытаетесь прочитать информацию.
port->read(packetBuffer, sizeof(Frame));
У вас уже есть проблемы, потому что вы пытались прочитать вдвое больше данных, которые написал отправитель. Размер int на 16-битной машине, выполняющей чтение, равен двум, а размер заголовка равен четырем. Но размер заголовка на отправляющем компьютере составлял восемь, по два дюйма по четыре байта каждый.
Теперь вы пытаетесь продвинуть указатель
m_iHeaderLength = sizeof(Header);
...
packetBuffer += m_iHeaderLength;
packetBuffer
будет по-прежнему указывать на данные, которые были в заголовке в кадре, отправленном отправителем.
Если есть проблема с переносимостью, то нет, это не решит проблему. m_pLayerHeader + m_iHeaderLength
а также &m_pLayerHeader[m_iHeaderLength]
полностью эквивалентны (в этом случае).