Search code examples
cpre-incrementunary-operator

How do Unary operators work in C, you cannot pre increment zero


I am confused about how Unary Operators work in C for Ones Complement, Logical Negation and preincrementing.

Ones complement works against 0 like this:

int main()
{
    int a;
    a = ~0;          // Ones complement
    printf("%d",a);  // prints as -1.
}

And logical negation works against 0 like this:

int main()
{
    int a;
    a = !0;          // Logical negation
    printf("%d",a);  // prints as 1.
}

But Preincrement against 0 generates a compiler error:

int main()
{
    int a;
    a = ++0;        //pre incrementing 0.  error: non-lvalue in increment
    printf("%d",a); 
}

Why don't all three work considering they are all Unary Operators?


Solution

  • The increment (++) and decrement (--) operators modify the thing that follows them. You can't modify a literal or a constant. In contrast, the ! and ~ operators merely operate on a value, they don't then assign the result anywhere.

    Loosely speaking, ++n means n = n + 1; n. That is, "take the value of n, add one to it, write that value back to n, and return the new value as the value of the expression." So ++0 would mean 0 = 0 + 1; 0: "take the value of 0, add one to it, write that back to 0, and return the new value as the result of the expression." Literals and constants cannot be left-hand values (you can't assign to them).

    In contrast, ~n means "take the value of n and apply a bitwise NOT operation to it, return the result as the result of the expression". n is unchanged, ~ doesn't write back the updated value to its operand.

    So for example:

    int n = 0;
    int a;
    a = ~n;
    printf("a = %d, n = %d\n", a, n); // "a = -1, n = 0" -- `n` is unchanged
    

    vs.

    int n = 0;
    int a;
    a = ++n;
    printf("a = %d, n = %d\n", a, n); // "a = 1, n = 1" -- `n` is changed
    

    Increment (++) and decrement (--) are just different in that way than for ! or ~ (or, I think, any other unary operator — at least, I can't immediately think of any others that modify their operand).