вернуть int или передать указатель int - что лучше? - PullRequest
6 голосов
/ 30 июня 2010

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

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

Или

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

Ответы [ 11 ]

7 голосов
/ 30 июня 2010

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

flag = SetBit(flag, 4);
6 голосов
/ 30 июня 2010

Ни.

int SetBit(int flag, int bit)
{
    return flag | 1 << bit;
}
5 голосов
/ 30 июня 2010

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

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 голосов
/ 30 июня 2010

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

#define BIT_SET(a, bit) ((a) | (1 << (bit)))
5 голосов
/ 30 июня 2010

Это зависит.

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

Если вы хотите сделать

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

сделай второй. Если хочешь

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

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

1 голос
/ 30 июня 2010

Второй лучше, потому что он не рухнет.

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

1 голос
/ 30 июня 2010

Это зависит.

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

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

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

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

1 голос
/ 30 июня 2010

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

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

0 голосов
/ 30 июня 2010

Если единственным шаблоном для использования функции будет "variable = doSomething (variable);" и производительность не является проблемой, я бы подумал "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 голосов
/ 30 июня 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...