возвратите интервал или передайте международный указатель — что лучше?

какой из этих двух лучше?

void SetBit(int *flag, int bit)
{
    *flag |= 1 << bit;
}

Или

int SetBit(int flag, int bit)
{
    flag |= 1 << bit;
    return flag;
}
6
задан emge 30 June 2010 в 14:06
поделиться

11 ответов

Второй мне нравится, потому что он не имеет побочных эффектов. Если вы хотите изменить флаг , вы можете просто присвоить результат самому себе:

flag = SetBit(flag, 4);
7
ответ дан 8 December 2019 в 03:00
поделиться

Ни то, ни другое.

int SetBit(int flag, int bit)
{
    return flag | 1 << bit;
}
6
ответ дан 8 December 2019 в 03:00
поделиться

Это зависит от обстоятельств.

первый - императивный стиль, второй - функциональный.

Если хочешь сделать

SetBit(SetBit(... SetBit(flag, b1), b2),...), bn)

, сделай второй. Если хотите

SetBit(&flag, b1)
SetBit(&flag, b2)
...
SetBit(&flag, bn)

, сделайте первый. В C я бы предпочел последнее (т.е. императивное). В других языках / контекстах первое может быть хорошей идеей.

5
ответ дан 8 December 2019 в 03:00
поделиться

Я бы использовал макрос:

#define BIT_SET(a, bit) ((a) | (1 << (bit)))
5
ответ дан 8 December 2019 в 03:00
поделиться

Мне больше нравится второй ...

Однако я бы рекомендовал изменить имя вашей функции, чтобы оно было более наглядным (при условии, что это настоящее имя). «SetBit» не очень хорошо описывает, что функция делает или возвращает:)

1
ответ дан 8 December 2019 в 03:00
поделиться

Честно говоря, я думаю, что это просто побуждает людей использовать «магические числа» в качестве флагов:

SetBit(&flags, 12); // 12 is the flag for Super mode

На самом деле вам нужны имена констант:

#define SUPERMODE_FLAG 12
...
SetBit(&flags, SUPERMODE_FLAG);

Но если вы собираетесь используйте именованные константы, вы также можете называть маски, а не номера битов, и в этом случае операция настолько проста, что нет необходимости во вспомогательной функции:

#define SUPERMODE_MASK (1 << 12)
....
flags |= SUPERMODE_MASK;

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

5
ответ дан 8 December 2019 в 03:00
поделиться

Второй лучше, потому что он не вылетит.

Первый будет может дать сбой, если вы передадите неверный указатель NULL , поэтому вам понадобится код для проверки и обработки этого.

1
ответ дан 8 December 2019 в 03:00
поделиться

Это зависит от того.

В этом случае действительно подойдет любой способ. Но я могу вспомнить два особых случая, когда я бы предпочел использовать указатель.

  1. Если тип, который вы передаете, большой и копирование значения будет дорогостоящим, используйте указатель из соображений производительности.

  2. Если вам нужно вернуть что-то еще, возможно, код состояния или индикатор успеха/неудачи, то вам нужно использовать указатель, чтобы оставить место для возврата значения, которое вам нужно вернуть.

Я лично думаю, что вне этих ситуаций второй вариант (передача/возврат по значению) более понятен и немного более читабелен.

1
ответ дан 8 December 2019 в 03:00
поделиться

Во-первых, нормально, если функции будут встроены. Без встраивания это слишком много накладных расходов, чтобы передавать указатели на целые числа. (В 64-битных архивах LP64 int - 4 байта, указатель - 8.)

Второе ... имя функции SetBit () может вызвать некоторую путаницу. Название подразумевает, что функция что-то меняет, а на самом деле - нет. Если вы согласны с названием, то это лучший вариант с точки зрения производительности.

Например. Ядро Linux для многих подобных вещей использует вариант указателя, поскольку часто расположение данных в памяти важно или требуется для переносимости. Но они либо делают все такие функции макросом препроцессора, либо помечают атрибут gcc always_inline. Для пользовательского программирования простых приложений я бы сказал, что предпочтение должно быть отдано второму. Только выберите лучшее имя.

0
ответ дан 8 December 2019 в 03:00
поделиться

Если единственным шаблоном использования функции будет «переменная = doSomething (переменная);» и производительность не является проблемой, я бы рассмотрел "doSomething (& variable);" чтобы быть более разборчивым. Единственный раз, когда я предпочел бы первое, было бы, если бы местом назначения иногда было что-то иное, чем источник, или если бы производительность была критичной, и компилятор не мог эффективно обрабатывать последний случай (часто встречается во встроенных системах).

Следует отметить, что последний формат позволяет то, что не позволяет первый. В стиле VB:

Sub OrBits(ByRef N as Integer, ByVal Bits as Integer)
  Dim OldValue as Integer
  Do
    OldValue = N
  Loop While Threading.Interlocked.CompareExchange(N, OldValue or Bits,  OldValue) <> OldValue
End Sub

Результатом этого кода всегда будет ИЛИ указанных битов на N, даже если что-то еще изменит N во время выполнения функции. Невозможно добиться такого поведения с помощью стратегии чтения и возврата.

0
ответ дан 8 December 2019 в 03:00
поделиться

Передайте int , чтобы сэкономить время на разыменовании указателя.

0
ответ дан 8 December 2019 в 03:00
поделиться
Другие вопросы по тегам:

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