Битовый сдвиг выше имеет ошибку:
unsigned short p = (packetBuffer[1] << 8) | packetBuffer[2];
если packetBuffer
находится в байтах (шириной 8 бит), то приведенный выше сдвиг может и превратит packetBuffer
в ноль, оставив вам только packetBuffer[2];
Несмотря на это, это по-прежнему предпочтительнее указателей. Чтобы избежать вышеупомянутой проблемы, я трачу несколько строк кода (кроме совершенно буквальной нулевой оптимизации), это приводит к тому же машинному коду:
unsigned short p;
p = packetBuffer[1]; p <<= 8; p |= packetBuffer[2];
Или, чтобы сэкономить несколько тактов и не сдвигать биты с конца:
unsigned short p;
p = (((unsigned short)packetBuffer[1])<<8) | packetBuffer[2];
Вы должны быть осторожны с указателями, оптимизатор вас укусит, а также с выравниванием памяти и длинным списком других проблем. Да, если все сделано правильно, это быстрее, если неправильно, ошибка может задержаться на долгое время и ударить в самый неподходящий момент.
Скажем, вы были ленивы и хотели выполнить 16-битную математику в 8-битном массиве. (маленький порядок байтов)
unsigned short *s;
unsigned char b[10];
s=(unsigned short *)&b[0];
if(b[0]&7)
{
*s = *s+8;
*s &= ~7;
}
do_something_With(b);
*s=*s+8;
do_something_With(b);
*s=*s+8;
do_something_With(b);
Нет никакой гарантии, что совершенно свободный от ошибок компилятор создаст код, который вы ожидаете. Массив байтов b
, отправленный в функцию do_something_with()
, никогда не может быть изменен операциями *s
. Ничто в приведенном выше коде не говорит, что так и должно быть. Если вы не оптимизируете свой код, вы можете никогда не столкнуться с этой проблемой (пока кто-нибудь не оптимизирует или не изменит компиляторы или версии компиляторов). Если вы используете отладчик, вы можете никогда не увидеть эту проблему (пока не станет слишком поздно).
Компилятор не видит связи между s и b, это два совершенно разных элемента. Оптимизатор может решить не записывать *s
обратно в память, потому что он видит, что *s
имеет ряд операций, поэтому он может сохранить это значение в регистре и сохранить его в памяти только в конце (если вообще когда-либо).
Есть три основных способа исправить указанную выше проблему с указателем:
- Объявить
s
изменчивым.
- Используйте союз.
- Используйте функцию или функции при изменении типов.
person
old_timer
schedule
20.11.2008