Home > OS >  What does return !!myVar mean?
What does return !!myVar mean?

Time:12-04

I'm reading an open code in C which uses glib, and I found this

gboolean function()
{
  guint myVar = 0;
  myVar = (!!globalVar1   !!globalVar2   !!globalVar3);
  return !!myVar;
}

I don't understand what's exactly happening with that double exclamation mark.

Thank you in advance.

CodePudding user response:

The unary ! operator performs a logical NOT operation. If its operand is non-zero, it evaluates to 0. If its operand is 0, it evaluates to 1.

When two of them are put together like this, it normalizes the operand to a boolean value. So if the operand is 0 the result is 0 and if the operand is non-zero the result is 1.

In the context of the larger expression:

myVar  = (!!globalVar1   !!globalVar2   !!globalVar3);

This will set myVar to a value between 0 and 3. Then this:

return !!myVar;

Normalizes that value to 0 or 1. So the end result is that 1 is returned if any of the 3 variables are non-zero, otherwise 0 is returned.

The body of the function can be rewritten as:

return globalVar1 || globalVar2  || globalVar3;

Which more clearly expresses the intent. The || operator does involve branching however, so the code as written was probably trying to avoid that branching.

Generally though, compilers are pretty good at optimizing, so such micro-optimizations are not really necessary.

CodePudding user response:

Let's at first consider this statement

myVar = (!!globalVar1   !!globalVar2   !!globalVar3);

Now according to the C Standard (6.5.3.3 Unary arithmetic operators)

5 The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E)

For example If you have a variable like this

int x = 10;

then applying the operator ! to the variable !x you will get 0. Applying the operator the second time !!x you will get 1. It is the same if to write x != 0.

So the result of the assignment is a non-zero value if at least one of the operands, globalVar1, globalVar2, and globalVar3. is not equal to 0.

The above statement can be rewritten the following way

myVar = ( ( globalVar1 != 0 )   ( globalVar2 != 0 )   ( globalVar3 != 0 ) );

The result of the assignment can be either 0 (if all operands are equal to 0), or 1 (if only one operand is not equal to 0), or 2 ( if two operands equal to 0), or 3 (if all operands are equal to 0).

The function need to return 1 if at least one operand is not equal to 0 or 1 otherwise.

You could just write in the return statement

return myVar != 0;

But the author of the code decided to write

return !!myVar;

It seems he likes very much the negation operator !.:)

The purpose of this "balancing act" with the negation operator is to return exactly either 0 or 1.

CodePudding user response:

It's the same as the single exclamation mark, twice. It's negating a value twice.

This has the effect of turning all integers to either 0 (if they were already 0) or 1 (if they were any non-zero value)

CodePudding user response:

!!val gives 0 if val is zero or 1 if val is not zero.

Example usage:

//function counting non zero elelemnts of array
size_t countNonZero(const int *array, size_t size)
{
    size_t count = 0;
    while(size--)
        count  = !!*array  ;
    return count;
}

In your example, there is no need of the !! operator as in C any non zero value is considered as the true. Simple || operator should be used.

that function should be rewritten as

gboolean function()
{
  return globalVar1 || globalVar2 || globalVar3;
}
  • Related