tags:

views:

250

answers:

11

which of these two is better?

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

Or

int SetBit(int flag, int bit)
{
    flag |= 1 << bit;
    return flag;
}
+7  A: 

I like the second one because it doesn't have any side effects. If you want to modify flag, you can simply assign the result to itself:

flag = SetBit(flag, 4);
Kristo
+5  A: 

Neither.

int SetBit(int flag, int bit)
{
    return flag | 1 << bit;
}
Billy ONeal
Definitely this. Don't dig in a parameter variable if you don't have a really good reason to. Return modified value and let the user assign it back into the variable if they like.
SF.
You don't think the compiler would maybe optimize that away anyway?
Platinum Azure
@Platinum: It's not a performance thing, it's a readability thing.
Billy ONeal
What's unreadable about one more line?
Platinum Azure
@Platinum: It's not that it's unreadable. It's that this one is more readable. With this version it's immediately clear that `flag` is not being modified. The original version has me looking up at the argument list to ensure `flag` is not a reference variable. (C doesn't have them, but C++ does, and so do most other languages)
Billy ONeal
subjective. I would prefer this just because it is more compact, but still subjective, and only-C-programmers have not to check if it is ref or not (the Q is tagged C); reading a source in Lang-X should create a context in mind to interpret Lang-X, not Lang-Y or most other languages; so that hardly we can be confused if we are in the C-context.
ShinTakezou
@Shin: Most of us know more than, and are experienced with more than, one language.
Billy ONeal
@Billy one more reason to get no confusion about flag being or not a reference variable in C
ShinTakezou
+1  A: 

I like the second one better...

However, I'd recommend changing the name of your function to be more descriptive (assuming this is the actual name). "SetBit" doesn't do much to describe what the function does or returns :)

Polaris878
It doesn't? It seems to make sense to me -- it sets the bit in the given flag variable.
Billy ONeal
Actually I disagree - the function sets a bit. The function could be used in any context where a bit must be set.
glowcoder
Sets "the bit" to what?
Polaris878
@Polaris: The one specified by the "bit" argument.
Billy ONeal
@Polaris: what would you call the function? I thought the name was clear and simple, all the function does is set the bit in the flag.
emge
Does it set the bit to a 1 or a 0?
Polaris878
@Polaris: It sets the bit. Setting a bit is assigning 1 to it. To reverse the process and set it to 0 is called resetting the bit.
Billy ONeal
I guess I'm just used to "set" being very generic from all the .NET I've been doing lately.
Polaris878
he pointed an interesting aspect anyway as side effect of the speech: SetBit lets me think it sets the bit, not that it returns it; so I would expect a "syntax" like `SetBit(a, bit)` and not `a = SetBit(a, bit)`; conventional anyway, since people gets fastly used to the assigned meaning that they can see in th way the func/macro is used. -- Often `set` means set to 1, and `clear` means `set to 0`, only convention widely used when handling bits.
ShinTakezou
+5  A: 

It depends.

first one is imperative style, second one is functional style.

If you want to do

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

do the second one. If you want

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

do the first one. In C, I would prefer the latter (ie. the imperative one). In other languages/contexts, the former may be a good idea.

Alexandre C.
A poor use of the functional style (deeply nesting functions) is not an excuse to avoid it. If you want to list them all out on separate lines you can just assign the result of SetBit to the flag variable on each line.
Billy ONeal
Would you seriously actually recommend using that first pattern in C, ever? (No downvote, but I have to question your mentioning it all because that will be nearly unreadable!)
Platinum Azure
@Platinum I wouldn't for sure, but I couldn't think of a good and immediate justification for the functional construct here.
Alexandre C.
Really, if you're doing SetBit on the same value a bunch of times in a row, I think it's probably a bit daft not to go with 'flag |= 0xDEADBEEF' or whatevet the bit pattern you want is. I would actually find that easier to read, and of course faster too. Unless you're using FD_SET for select() or something. Or: 'flag |= (FLAG_A | FLAG_B | ...)' if ypu have approproate constants representing the bits to set.
Owen S.
Functional style: 'reduce SetBit flag [b1, b2, ...]' :-)
Owen S.
@Owen: yep, but hard to do properly in C :(
Alexandre C.
+1  A: 

It depends.

In that case, either way would really work. But I can think of two special cases where I would favor using a pointer.

  1. If the type you're passing in is large and a value copy would be expensive, use a pointer for performance reasons.

  2. If you need to return something else, maybe a status code or success/failure indication, then you need to use the pointer so that you can leave room to return the value you need to return.

I personally think that outside of those situations, the second one (pass/return by value) is clearer and slightly more readable.

Platinum Azure
+1  A: 

The second is better because it won't crash.

The first one will could crash if you pass in an NULL invalid pointer so you'd need to have some code to check and handle that.

Amardeep
A: 

pass an int to save time dereferencing the value of address

ultrajohn
This function is going to be inlined by any reasonable compiler anyway -- I'd not worry about performance here.
Billy ONeal
Especially in the embedded systems world, not all compilers will inline such things. Further, the <i>pattern</i> arises in many cases where the code is sufficiently complex that inlining it would be impractical. By my interpretation, the question was not about how he should set bits in a variable, but about which pattern of coding was better.
supercat
+5  A: 

I would use a macro:

#define BIT_SET(a, bit) ((a) | (1 << (bit)))
X-N2O
Why not, but I'd still name it SET_BIT ;)
Alexandre C.
+1 I would use a macro too
Hernán Eche
+1 definitely a macro (a function call is expensive in such cases)
Iulian Şerbănoiu
a classical usage of macros, I would say... +1 me too
ShinTakezou
+5  A: 

To be honest, I think this just encourages people to use "magic numbers" as flags:

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

What you actually want is named constants:

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

But if you're going to use named constants, you might as well name masks rather than bit numbers, in which case the operation is so simple there's no need for a helper function:

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

In the unusual case that you're manipulating individual bits by number, without knowing what they mean, then I prefer the second for the same reason as Kristo - I find side-effect-free functions slightly easier to reason about than mutators.

Steve Jessop
A: 

First is OK if functions is going to be inlined. Without inlining that's bit too much overhead to pass around pointers to ints. (On 64bit LP64 archs, int is 4 bytes, pointer is 8.)

Second ... function name SetBit() is going to cause some mild confusion. Name implies that function changes something while in fact it doesn't. As long as you are OK with the name, then it is performance-wise a better option.

E.g. Linux kernel uses for many similar things the pointer variant, since often memory location of the datum is important or required for portability. But they either make all such functions a preprocessor macro or mark with gcc's always_inline attribute. For user-land, plain application programming, I'd say the second should be preferred. Only pick a better name.

Dummy00001
A: 

If the only pattern for using the function will be "variable = doSomething(variable);" and performance is not an issue, I would consider "doSomething(&variable);" to be more legible. The only time I would favor the former would be if the destination was sometimes something other than the source, or if performance were crucial and one's compiler could not efficiently handle the latter case (common on embedded systems).

It should be noted that the latter format allows something the former does not. In VB-style:

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

The effect of this code will always be to OR the specified bits into N, even if something else changes N while the function is running. It is not possible to achieve such behavior with the read-and-return strategy.

supercat