Arithmetic Operators
These perform standard mathematical operations. All of these are left associative.
+,-,*,/: Addition, Subtraction, Multiplication, Division.%(Modulo): Returns the remainder of an integer division.For example
-10 % 4will yield-2.
Important: The sign of the result for % is implementation-defined for negative operands in C89, but since C99, it follows the dividend (the first operand). -7 % 3 is 1.
Unary Operators
A unary operator is an operator that acts on a single operand to produce a new value. This contrasts with binary operators (like +, *) which act on two operands. All these operators are right associative.
The unary operators in C are:
+(Unary Plus): Indicates a positive value. (e.g.,+5). It's rarely used as values are positive by default.-(Unary Minus): Negates the value of its operand. (e.g.,5).!(Logical NOT): Inverts the truth value of its operand. If the operand is non-zero (true), it returns0(false). If the operand is zero (false), it returns1(true). (e.g.,!(a == b)is equivalent toa != b).~(Bitwise NOT): Flips every bit in the operand. (e.g.,~0b1010becomes0b0101). This is also called the one's complement.sizeof: Returns the size in bytes of its operand (a type or a variable). This is evaluated at compile-time, not runtime. (e.g.,sizeof(int),sizeof myArray).Note that
sizeofcan be used on both types and variables.&(Address-of): Returns the memory address of its operand. (e.g.,&variablegives you a pointer tovariable).*(Dereference): Accesses the value a pointer points to. It is the inverse of the address-of operator. (e.g.,pointergives the value stored at the address held bypointer).
Increment/Decrement Operators
These are a specific, very common subset of unary operators that modify their operand.
++(Increment): Increases a variable's value by 1.--(Decrement): Decreases a variable's value by 1.
They can be used in two forms, which affects when the increment happens:
- Prefix (e.g.,
++a): The increment happens first, and the new value is then used in the expression. - Postfix (e.g.,
a++): The current value is used in the expression first, and then the increment happens.
int a = 5;
int b = ++a; // a becomes 6, then b is assigned 6.
int c = a++; // c is assigned 6, then a becomes 7.Relational Operators
These compare two operands and return an integer value of 1 (true) or 0 (false).
==(Equal to),!=(Not equal to)<(Less than),>(Greater than)<=(Less than or equal to),>=(Greater than or equal to)
Crucial Note: The equality operator is == (double equals), not = (single equals, which is assignment). Using = in a condition is a common bug.
Logical Operators
These operate on true/false values (in C, any non-zero is true, zero is false).
&&(Logical AND): Returns1only if both operands are true.||(Logical OR): Returns1if at least one operand is true.
Short-Circuiting: This is a critical behavior. If the result can be determined by the first operand, the second is never evaluated.
(a != 0) && (b / a > 5): Ifais 0, the second expression(b / a)is skipped, preventing a division-by-zero error.(a == 0) || (b / a > 5): Ifais 0, the second expression is skipped.
Bitwise Operators
These perform operations on the individual bits of integer operands.
&(Bitwise AND): A bit in the result is 1 only if both corresponding bits are 1. Often used for masking (turning bits off).|(Bitwise OR): A bit in the result is 1 if at least one corresponding bit is 1. Often used for turning bits on.^(Bitwise XOR): A bit in the result is 1 if the corresponding bits are different. Often used for toggling bits.<<(Left Shift): Shifts bits to the left. Equivalent to multiplying by 2 for each shift (if no overflow).>>(Right Shift): Shifts bits to the right. Equivalent to integer division by 2 for each shift. Whether it's a logical (zeros shifted in) or arithmetic (sign bit preserved) shift is implementation-defined for negative numbers.
Assignment Operators
These assign a value to a variable.
=(Simple Assignment):a = b;- Compound Assignment: These perform an operation and then assign the result. The form is
op=. They are shorthand and often more efficient.a += b;is equivalent toa = a + b;- Others:
=,=,/=,%=,&=,|=,^=,<<=,>>=
The assignment operator is an expression with the following properties:
- Returns the value being assigned
- Right-to-left associativity
As a result we can write statement such as:
a = b = c = 10;
a = (b = (c = 10)); // Equivalent to the above statementThis works because the expression c = 10 assigns the number 10 to a variables and the expression c = 10 itself has the value that was assigned: 10. Thus, all the variables in the expression get set to 10. Such behaviour is often referred to as cascading.
Other Important Operators
- Conditional (Ternary) Operator (
? :): A shorthand for anif-elsestatement.Syntax:
condition ? expression_if_true : expression_if_falseint max = (a > b) ? a : b; // Sets max to the larger of a or b. - Comma Operator (
,): Evaluates two expressions, discarding the result of the first and returning the result of the second. It has the lowest precedence.int a = (x++, y++); // x is incremented, then y is incremented and assigned to a.It's most commonly used in the initialization and increment parts of a
forloop:for(i=0, j=10; i<j; i++, j--). - Member Operators:
.(Direct Member Access): Accesses a member of a struct or union variable.myStruct.age>(Indirect Member Access): Accesses a member of a struct or union through a pointer.myStructPtr->ageis equivalent to(*myStructPtr).age.
Here is a summary of operators:
int a = 5, b = 2;
int sum = a + b; /* arithmetic */
int mod = a % b; /* remainder */
int *p = &a; /* address-of */
int val = *p; /* dereference */
p++; /* pointer arithmetic */
int t = (a > b) ? a : b; /* conditional */
a <<= 1; /* compound assignment (left shift) */
int cond = (a > 0) && (b != 0); /* logical and (short-circuits) */Evaluation Order
This is a critical and often misunderstood point. Precedence and associativity determine grouping, not the order of evaluation of operands.
Precedence: Determines which operator is bound more tightly to its operands. For example, in a + b * c, * has higher precedence than +, so it's evaluated as a + (b * c).
Here is a detailed look into precedence.
The following table summarizes the precedence and associativity of C operators, listed from highest precedence (evaluated first) to lowest precedence (evaluated last).
| Precedence | Operator | Description | Associativity |
|---|---|---|---|
| 1 | () [] . -> ++ -- (postfix) | Grouping, array subscript, member access, post-increment/decrement | Left-to-right |
| 2 | ++ -- + - ! ~ * & sizeof (type) | Unary prefix increment/decrement, plus/minus, logical/bitwise NOT, dereference, address-of, size, type cast | Right-to-left |
| 3 | * / % | Multiplication, division, remainder | Left-to-right |
| 4 | + - | Addition, subtraction | Left-to-right |
| 5 | << >> | Bitwise left and right shift | Left-to-right |
| 6 | < <= > >= | Relational less than, less than or equal to, greater than, greater than or equal to | Left-to-right |
| 7 | == != | Equality, inequality | Left-to-right |
| 8 | & | Bitwise AND | Left-to-right |
| 9 | ^ | Bitwise XOR (exclusive OR) | Left-to-right |
| 10 | | | Bitwise inclusive OR | Left-to-right |
| 11 | && | Logical AND | Left-to-right |
| 12 | || | Logical OR | Left-to-right |
| 13 | ?: | Conditional (ternary) operator | Right-to-left |
| 14 | = += -= *= /= %= <<= >>= &= ^= |= | Assignment and compound assignment | Right-to-left |
| 15 | , | Comma operator (sequential evaluation) | Left-to-right |
Associativity: Determines the order of evaluation when operators of the same precedence appear in an expression.
- Left-to-Right:
a - b - cis(a - b) - c - Right-to-Left:
a = b = cisa = (b = c)
Note: Avoid using increment/decrement operators (++, --) in complex expressions where the order of evaluation matters, as it can lead to undefined behavior. a[i] = i++; is a classic example of bad code.