Хорошая Форма: Указатель по сравнению с локальной переменной по сравнению с Индексом массива

Простите мне, если это сталкивается тривиального вопроса - я обычно - парень систем управления (plc's и автоматизация), но нашел меня вовлеченным в некоторые встроенные проекты микроконтроллера и ПК в последнее время.

Скажем, у меня есть функция, которая принимает указатель на массив 'байтов команды', обычно 5 или 10 байтов в длине, как так:

char cmd_i2c_read(unsigned char *cmd, unsigned short cmd_len) { ... }

Я хочу декодировать байты команды (*cmd).

Это лучше формируется к:

  1. Создайте локальные переменные, указывающие на цель каждого байта:

    unsigned char device_address = cmd[2];
    unsigned char register_address = cmd[3];
    unsigned char num_bytes = cmd[4];
    // use the local variables: if(num_bytes ≤ 0xFF) { do_stuff(device_address, register_address, num_bytes); }
  2. Создайте локальные указатели:

    unsigned char *device_address = &cmd[2];
    unsigned char *register_address = &cmd[3];
    unsigned char *num_bytes = &cmd[4];
    // use the pointers: if(*num_bytes ≤ 0xFF) { do_stuff(*device_address, *register_address, *num_bytes); }
  3. Индексируйте *cmd массив непосредственно:
    if(cmd[4] <= 0xFF) { do_stuff(cmd[2], cmd[3], cmd[4]); }

5
задан user158485 23 February 2010 в 20:48
поделиться

7 ответов

Вариант 1 понятен, но немного многословен. Вариант 2 мне совсем не нравится, а 3 трудно понять. Лично я предпочитаю использовать структуры для таких вещей.

typedef struct  {
   unsigned char whatever[2];
   unsigned char device_address;
   unsigned char register_address;
   unsigned char num_bytes;
   }  CMD;

CMD * pcmd = (CMD *)&cmd[0];

// use the local variables:
if(num_bytes ≤ 0xFF) {
    do_stuff(pcmd->device_address, pcmd->register_address, pcmd->num_bytes);
4
ответ дан 18 December 2019 в 14:45
поделиться

Я предпочитаю пункт 3, но все зависит от предпочтений.

3
ответ дан 18 December 2019 в 14:45
поделиться

ИМХО, первый способ лучше. Его гораздо легче читать, чем номер 3, потому что вам не нужно знать сигнатуру функции, чтобы понять, какие у нее параметры.

Для больших структур данных я бы выбрал номер 2, т.е. использовал бы указатель, чтобы не копировать значения. Но в данном случае разница не существенна, и я думаю, что */& немного ухудшают читабельность.

3
ответ дан 18 December 2019 в 14:45
поделиться

Определенно №1. Это делает остальную часть кода более читаемой, а использование указателя вместо обычной переменной усложняет задачу без всякой причины. Компилятор оптимизирует любой микроскопический прирост производительности, который вы можете получить от №3.

2
ответ дан 18 December 2019 в 14:45
поделиться

1 мне нравится больше всего, он намного читабельнее, чем другие.

Если производительность является важным вопросом (я имею в виду важность, например, «нам нужно каждые 0.01% ускорение, которое мы можем получить "), вам придется провести тест, потому что это действительно зависит от компилятора, какая последовательность завершится в самом быстром коде (1 может содержать ненужные копии, 2 может содержать избыточные нагрузки из-за ограничений наложения указателей, 3 может приведет к чрезмерной загрузке, если распределитель регистров действительно испорчен)

0
ответ дан 18 December 2019 в 14:45
поделиться

Для меня это зависит от того, что вы будете делать с буфером,

При прочих равных условиях, я бы предпочел, чтобы буфер был структурой (предполагаются искривления выравнивания), а в противном случае, чтобы буфер индексировался напрямую, хотя и не с помощью магических чисел.

0
ответ дан 18 December 2019 в 14:45
поделиться

Если бы это был я, я бы написал это как №3, но с символическими именами для индексов массива, чтобы улучшить читаемость: -

#define DEVICE_ADDRESS 2
#define REGISTER_ADDRESS 3
#define NUM_BYTES 4

if (cmd[NUM_BYTES] <= 0xFF) {
    do_stuff(cmd[DEVICE_ADDRESS], cmd[REGISTER_ADDRESS], cmd[NUM_BYTES]);
}

Вы, конечно, можете замените макросы на const int, enums и т. д. Причина, по которой мне нравится этот вариант, заключается в том, что два других варианта требуют использования дополнительных локальных переменных. Компилятор может или не может оптимизировать их, в зависимости от его реализации и выбранного вами уровня оптимизации, но мне они просто кажутся ненужным уровнем дополнительного косвенного обращения.

1
ответ дан 18 December 2019 в 14:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: