Arithmetic Operators
C provides several arithmetic operators for mathematical computations:
+ - * / %
- All operators except modulus (%) work with both integers and floating-point numbers
- Division (/) performs integer division when both operands are integers, and floating-point division when either operand is floating-point
- Modulus (%) requires integer operands and returns the remainder after division
Shift Operators
Shift operators move bits left or right within integer values:
<< // Left shift
>> // Right shift
These operators work exclusively with integer types.
Binary Number Representations
Integers in memory use three binary representations:
- Original code: Direct binary translation of the numerical value
- One's complement: Original code with bits flipped (except sign bit)
- Two's compliment: One's compliment plus one (used for arithmetic operations)
Positive numbers have identical representations across all three formats. Negative numbers follow specific conversion rules between representations.
Left Shift Operation
Left shifting moves bits toward higher significance positions:
int value = 4;
int shifted = value << 1; // Result: 8
Each left shift effectively multiplies the value by two, filling vacated bits with zeros.
Right Shift Operation
Right shifting moves bits toward lower significance positions. Behavior varies by implementation:
- Logical shift: Fills vacant bits with zeros
- Arithmetic shift: Preserves the sign bit in vacant positions
Most compilers use arithmetic shifting for signed integers.
Bitwise Operators
Bitwise operators perform logical operations on individual bits:
Bitwise AND (&)
Sets result bits to 1 only when both corresponding operand bits are 1:
int result = 3 & -5; // Result: 3
Bitwise OR (|)
Sets result bits to 1 when either corresponding operand bit is 1:
int result = 3 | -5; // Result: -5
Bitwise XOR (^)
Sets result bits to 1 when corresponding operand bits differ:
int result = 3 ^ -5; // Result: -8
Key properties: a ^ a = 0 and a ^ 0 = a
Bitwise NOT (~)
Inverts all bits of the operand:
int result = ~0; // Result: -1
Practical Applications
Bitwise operators enable efficient value manipulation:
// Swap values without temporary storage
int x = 3, y = 5;
x = x ^ y;
y = x ^ y;
x = x ^ y;
// Set specific bit
int number = 10;
number = number | (1 << 2); // Set third bit
// Clear specific bit
number = number & ~(1 << 2); // Clear third bit
Assignment Operators
Assignment operators modify variible values:
int counter = 10;
counter = 5; // Simple assignment
// Compound assignments
counter += 5; // counter = counter + 5
counter -= 3; // counter = counter - 3
counter *= 2; // counter = counter * 2
counter /= 4; // counter = counter / 4
counter %= 3; // counter = counter % 3
Unary Operators
Unary operators work with single operands:
! // Logical negation
- // Arithmetic negation
+ // Positive indication
& // Address extraction
sizeof // Size determination
~ // Bitwise complement
-- // Decrement
++ // Increment
* // Pointer dereference
(type) // Type conversion
Sizeof Operator
Determines memory size of data types or variables:
int data[10];
printf("Array size: %zu\n", sizeof(data)); // 40 bytes
printf("Element size: %zu\n", sizeof(data[0])); // 4 bytes
printf("Pointer size: %zu\n", sizeof(&data[0])); // 4 or 8 bytes
Increment/Decrement Operators
Prefix and postfix variants modify evaluation order:
int value = 10;
int a = ++value; // value=11, a=11 (prefix)
int b = value++; // value=12, b=11 (postfix)
Relational and Logical Operators
Comparison and Boolean operations:
> >= < <= != == // Relational operators
&& || ! // Logical operators
Logical operators implement short-circuit evaluation.
Conditional Operator
Ternary operator for conditional expressions:
int maximum = (a > b) ? a : b;
int absolute = (value >= 0) ? value : -value;
Comma Operator
Evaluates multiple expressions, returning the last result:
int result = (a = 5, b = 10, a + b); // result = 15
Specialized Operators
Subscript Operator
Accesses array elements:
int numbers[] = {1, 2, 3, 4};
int element = numbers[2]; // element = 3
Function Call Operator
Invokes functions with arguments:
printf("Result: %d\n", calculate(5, 10));
Structure Member Access
Accesses structure members through variables or pointers:
typedef struct {
char name[20];
double price;
} Product;
Product item = {"Book", 25.99};
Product *ptr = &item;
printf("Name: %s\n", item.name); // Direct access
printf("Price: %.2f\n", ptr->price); // Pointer access
Expression Evaluation
Type Promotion
Small integer types promote to int during expressions:
char a = 10, b = 20;
int result = a + b; // chars promote to int
Arithmetic Conversion
Mixed-type operands convert according to type hierarchy:
int integer = 5;
float real = 2.5;
double result = integer + real; // integer converts to float
Operator Precedence and Associativity
Expression evaluation follows operator precedence rules. Complex expressions should use parentheses for clarity:
// Clear precedence with parentheses
int calculation = (a + b) * (c - d);