Introduction to Arithmetic Operations in C
C provides a comprehensive set of arithmetic operators for performing mathematical calculations. Understanding these operations is fundamental to C programming, from simple calculations to complex mathematical computations.
Core Arithmetic Operators
Basic Arithmetic Operators
| Operator | Name | Description | Example |
|---|---|---|---|
+ | Addition | Adds two operands | a + b |
- | Subtraction | Subtracts second operand from first | a - b |
* | Multiplication | Multiplies two operands | a * b |
/ | Division | Divides first operand by second | a / b |
% | Modulus | Returns remainder of division | a % b |
Basic Arithmetic Examples
#include <stdio.h>
int main() {
int a = 10, b = 3;
printf("a = %d, b = %d\n", a, b);
printf("Addition (a + b) = %d\n", a + b);
printf("Subtraction (a - b) = %d\n", a - b);
printf("Multiplication (a * b) = %d\n", a * b);
printf("Division (a / b) = %d\n", a / b); // Integer division
printf("Modulus (a %% b) = %d\n", a % b); // Remainder
return 0;
}
Output:
a = 10, b = 3 Addition (a + b) = 13 Subtraction (a - b) = 7 Multiplication (a * b) = 30 Division (a / b) = 3 Modulus (a % b) = 1
Integer vs Floating-Point Arithmetic
Integer Division vs Floating-Point Division
#include <stdio.h>
int main() {
int a = 10, b = 3;
float x = 10.0, y = 3.0;
printf("=== Integer Division ===\n");
printf("10 / 3 = %d\n", 10 / 3); // Result: 3
printf("10 %% 3 = %d\n\n", 10 % 3); // Result: 1
printf("=== Floating-Point Division ===\n");
printf("10.0 / 3.0 = %.2f\n", 10.0 / 3.0); // Result: 3.33
printf("10.0 / 3 = %.2f\n", 10.0 / 3); // Mixed types
printf("=== Type Casting ===\n");
printf("(float)10 / 3 = %.2f\n", (float)a / b); // Explicit casting
printf("10 / (float)3 = %.2f\n", a / (float)b); // Explicit casting
return 0;
}
Output:
=== Integer Division === 10 / 3 = 3 10 % 3 = 1 === Floating-Point Division === 10.0 / 3.0 = 3.33 10.0 / 3 = 3.33 === Type Casting === (float)10 / 3 = 3.33 10 / (float)3 = 3.33
Operator Precedence and Associativity
Precedence Table (Highest to Lowest)
| Level | Operator | Description | Associativity |
|---|---|---|---|
| 1 | () | Parentheses | Left to Right |
| 2 | ++ -- | Postfix increment/decrement | Left to Right |
| 3 | ++ -- + - ! ~ | Unary operators | Right to Left |
| 4 | * / % | Multiplicative | Left to Right |
| 5 | + - | Additive | Left to Right |
| 6 | << >> | Bitwise shift | Left to Right |
| 7 | < <= > >= | Relational | Left to Right |
| 8 | == != | Equality | Left to Right |
| 9 | & | Bitwise AND | Left to Right |
| 10 | ^ | Bitwise XOR | Left to Right |
| 11 | | | Bitwise OR | Left to Right |
| 12 | && | Logical AND | Left to Right |
| 13 | || | Logical OR | Left to Right |
| 14 | ?: | Ternary conditional | Right to Left |
| 15 | = += -= etc. | Assignment | Right to Left |
| 16 | , | Comma | Left to Right |
Precedence Examples
#include <stdio.h>
int main() {
int a = 5, b = 3, c = 2;
int result;
printf("=== Operator Precedence ===\n\n");
// Multiplication before addition
result = a + b * c;
printf("a + b * c = %d (b * c first)\n", result);
// Parentheses override precedence
result = (a + b) * c;
printf("(a + b) * c = %d\n", result);
// Complex expression
result = a * b + c / 2 - a % b;
printf("a * b + c / 2 - a %% b = %d\n", result);
// Step-by-step evaluation
printf("\n=== Step-by-step ===\n");
printf("Expression: 5 + 3 * 2 - 8 / 4\n");
printf("Step 1: 5 + 6 - 8 / 4 (3 * 2 = 6)\n");
printf("Step 2: 5 + 6 - 2 (8 / 4 = 2)\n");
printf("Step 3: 11 - 2 (5 + 6 = 11)\n");
printf("Result: 9\n");
return 0;
}
Compound Assignment Operators
Assignment Operators Table
| Operator | Example | Equivalent to |
|---|---|---|
+= | a += b | a = a + b |
-= | a -= b | a = a - b |
*= | a *= b | a = a * b |
/= | a /= b | a = a / b |
%= | a %= b | a = a % b |
Compound Assignment Examples
#include <stdio.h>
int main() {
int x = 10;
printf("Initial value: x = %d\n", x);
x += 5; // x = x + 5
printf("After x += 5: %d\n", x);
x -= 3; // x = x - 3
printf("After x -= 3: %d\n", x);
x *= 2; // x = x * 2
printf("After x *= 2: %d\n", x);
x /= 4; // x = x / 4
printf("After x /= 4: %d\n", x);
x %= 3; // x = x % 3
printf("After x %%= 3: %d\n", x);
return 0;
}
Output:
Initial value: x = 10 After x += 5: 15 After x -= 3: 12 After x *= 2: 24 After x /= 4: 6 After x %= 3: 0
Increment and Decrement Operators
Prefix vs Postfix
#include <stdio.h>
int main() {
int a = 5, b = 5;
int result1, result2;
printf("=== Prefix vs Postfix ===\n\n");
// Postfix: use then increment
result1 = a++;
printf("Postfix (a++):\n");
printf(" result = %d (original value used)\n", result1);
printf(" a now = %d (after increment)\n", a);
printf("\n");
// Prefix: increment then use
result2 = ++b;
printf("Prefix (++b):\n");
printf(" result = %d (incremented value used)\n", result2);
printf(" b now = %d\n", b);
printf("\n=== In Expressions ===\n");
int x = 5, y = 5;
int z = x++ + ++y;
printf("x = 5, y = 5\n");
printf("x++ + ++y = %d\n", z);
printf("After: x = %d, y = %d\n", x, y);
return 0;
}
Output:
=== Prefix vs Postfix === Postfix (a++): result = 5 (original value used) a now = 6 (after increment) Prefix (++b): result = 6 (incremented value used) b now = 6 === In Expressions === x = 5, y = 5 x++ + ++y = 11 After: x = 6, y = 6
Bitwise Arithmetic Operations
Bitwise Operators
| Operator | Name | Description |
|---|---|---|
& | AND | Bitwise AND |
| | OR | Bitwise OR |
^ | XOR | Bitwise XOR |
~ | NOT | Bitwise complement |
<< | Left shift | Shift bits left |
>> | Right shift | Shift bits right |
Bitwise Examples
#include <stdio.h>
void printBinary(unsigned int n) {
for (int i = 31; i >= 0; i--) {
printf("%d", (n >> i) & 1);
if (i % 8 == 0) printf(" ");
}
printf("\n");
}
int main() {
unsigned int a = 60; // 0011 1100
unsigned int b = 13; // 0000 1101
printf("a = %d (", a);
printBinary(a);
printf("b = %d (", b);
printBinary(b);
printf("\n=== Bitwise Operations ===\n\n");
printf("a & b = %3d (", a & b);
printBinary(a & b);
printf("a | b = %3d (", a | b);
printBinary(a | b);
printf("a ^ b = %3d (", a ^ b);
printBinary(a ^ b);
printf("~a = %3d (", ~a);
printBinary(~a);
printf("a << 2 = %3d (", a << 2);
printBinary(a << 2);
printf("a >> 2 = %3d (", a >> 2);
printBinary(a >> 2);
return 0;
}
Output:
a = 60 (00111100 00000000 00000000 00000000 ) b = 13 (00001101 00000000 00000000 00000000 ) === Bitwise Operations === a & b = 12 (00001100 00000000 00000000 00000000 ) a | b = 61 (00111101 00000000 00000000 00000000 ) a ^ b = 49 (00110001 00000000 00000000 00000000 ) ~a = -61 (11000011 11111111 11111111 11111111 ) a << 2 = 240 (11110000 00000000 00000000 00000000 ) a >> 2 = 15 (00001111 00000000 00000000 00000000 )
Type Conversion (Casting)
Implicit vs Explicit Conversion
#include <stdio.h>
int main() {
printf("=== Implicit Type Conversion ===\n\n");
int i = 10;
float f = 3.14;
double d = 5.7;
// Integer + float -> float
float result1 = i + f;
printf("int + float: %d + %.2f = %.2f\n", i, f, result1);
// Integer + double -> double
double result2 = i + d;
printf("int + double: %d + %.1f = %.1f\n", i, d, result2);
// All mixed
double result3 = i + f + d;
printf("int + float + double = %.2f\n\n", result3);
printf("=== Explicit Type Conversion (Casting) ===\n\n");
int x = 10, y = 3;
// Without casting
float div1 = x / y;
printf("Without casting: %d / %d = %.2f\n", x, y, div1);
// With casting
float div2 = (float)x / y;
printf("With casting: (float)%d / %d = %.2f\n", x, y, div2);
// Multiple casts
float div3 = (float)x / (float)y;
printf("Both cast: (float)%d / (float)%d = %.2f\n", x, y, div3);
return 0;
}
Common Arithmetic Functions
Math Library Functions
#include <stdio.h>
#include <math.h>
int main() {
double x = 25.0;
double y = 3.0;
printf("=== Math Library Functions ===\n\n");
printf("x = %.2f, y = %.2f\n\n", x, y);
printf("sqrt(%.2f) = %.2f\n", x, sqrt(x));
printf("pow(%.2f, %.2f) = %.2f\n", y, y, pow(y, y));
printf("exp(%.2f) = %.2f\n", y, exp(y));
printf("log(%.2f) = %.2f\n", x, log(x));
printf("log10(%.2f) = %.2f\n", x, log10(x));
printf("fabs(%.2f) = %.2f\n", -x, fabs(-x));
printf("ceil(%.2f) = %.2f\n", 3.14, ceil(3.14));
printf("floor(%.2f) = %.2f\n", 3.14, floor(3.14));
printf("round(%.2f) = %.2f\n", 3.5, round(3.5));
printf("\n=== Trigonometric Functions ===\n");
double angle = 45.0;
double rad = angle * M_PI / 180.0;
printf("sin(%.0f°) = %.4f\n", angle, sin(rad));
printf("cos(%.0f°) = %.4f\n", angle, cos(rad));
printf("tan(%.0f°) = %.4f\n", angle, tan(rad));
return 0;
}
Note: Compile with -lm flag: gcc program.c -o program -lm
Integer Overflow and Underflow
Understanding Overflow
#include <stdio.h>
#include <limits.h>
int main() {
printf("=== Integer Overflow ===\n\n");
int max = INT_MAX;
int min = INT_MIN;
printf("INT_MAX = %d\n", max);
printf("INT_MIN = %d\n\n", min);
// Overflow
printf("INT_MAX + 1 = %d (overflow)\n", max + 1);
printf("INT_MIN - 1 = %d (underflow)\n\n", min - 1);
// Unsigned overflow (wraps around)
unsigned int umax = UINT_MAX;
printf("UINT_MAX = %u\n", umax);
printf("UINT_MAX + 1 = %u (wraps to 0)\n\n", umax + 1);
printf("=== Safe Arithmetic ===\n\n");
int a = 2000000000;
int b = 2000000000;
// Dangerous
int dangerous = a + b;
printf("%d + %d = %d (may overflow)\n", a, b, dangerous);
// Safe check
if (a > INT_MAX - b) {
printf("Overflow would occur!\n");
} else {
int safe = a + b;
printf("Safe result: %d\n", safe);
}
return 0;
}
Advanced Arithmetic Techniques
Efficient Multiplication and Division by Powers of 2
#include <stdio.h>
int main() {
int x = 42;
printf("x = %d\n\n", x);
// Multiplication by 2 (faster with shift)
printf("x * 2 = %d\n", x * 2);
printf("x << 1 = %d (shift)\n\n", x << 1);
// Division by 2 (faster with shift)
printf("x / 2 = %d\n", x / 2);
printf("x >> 1 = %d (shift)\n\n", x >> 1);
// Multiplication by 4
printf("x * 4 = %d\n", x * 4);
printf("x << 2 = %d (shift)\n\n", x << 2);
// Check if number is odd/even
printf("x %% 2 = %d (remainder)\n", x % 2);
printf("x & 1 = %d (bitwise AND)\n\n", x & 1);
// Swap without temporary variable
int a = 5, b = 3;
printf("Before swap: a = %d, b = %d\n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("After swap (addition): a = %d, b = %d\n", a, b);
// Reset
a = 5; b = 3;
// XOR swap (for integers)
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("After swap (XOR): a = %d, b = %d\n", a, b);
return 0;
}
Common Pitfalls and Best Practices
1. Integer Division Gotchas
#include <stdio.h>
int main() {
// Wrong way
float result1 = 5 / 2; // Does integer division first
printf("5 / 2 = %.2f (WRONG - integer division)\n", result1);
// Right way
float result2 = 5.0 / 2; // Float division
float result3 = (float)5 / 2; // Explicit cast
printf("5.0 / 2 = %.2f (CORRECT)\n", result2);
printf("(float)5 / 2 = %.2f (CORRECT)\n\n", result3);
return 0;
}
2. Modulo with Negative Numbers
#include <stdio.h>
int main() {
printf("=== Modulo with Negative Numbers ===\n\n");
printf("5 %% 3 = %d\n", 5 % 3);
printf("-5 %% 3 = %d\n", -5 % 3);
printf("5 %% -3 = %d\n", 5 % -3);
printf("-5 %% -3 = %d\n\n", -5 % -3);
// Note: Result sign follows dividend in C
printf("Note: In C, result sign follows dividend\n");
return 0;
}
3. Operator Precedence Confusion
#include <stdio.h>
int main() {
int a = 5, b = 3, c = 2;
// What does this do?
int result = a << b + c; // Actually a << (b + c), not (a << b) + c
printf("a << b + c = %d\n", result);
printf("Because: b + c = %d, then a << %d = %d\n",
b + c, b + c, result);
// Use parentheses for clarity
int correct = (a << b) + c;
printf("(a << b) + c = %d\n", correct);
return 0;
}
4. Floating-Point Precision
#include <stdio.h>
#include <math.h>
int main() {
printf("=== Floating-Point Precision ===\n\n");
double a = 0.1;
double b = 0.2;
double c = a + b;
printf("0.1 + 0.2 = %.20f\n", c);
printf("Expected: 0.3\n");
// Never compare floating-point directly
if (c == 0.3) {
printf("Equal! (this won't print)\n");
} else {
printf("Not equal due to precision\n");
}
// Use epsilon comparison
double epsilon = 0.0000001;
if (fabs(c - 0.3) < epsilon) {
printf("Equal within epsilon\n");
}
return 0;
}
Performance Considerations
Optimization Techniques
#include <stdio.h>
int main() {
int x = 1000;
printf("=== Performance Optimizations ===\n\n");
// Multiplication/division by powers of 2
printf("x * 8 = %d\n", x * 8);
printf("x << 3 = %d (faster)\n\n", x << 3);
// Modulo by powers of 2
printf("x %% 8 = %d\n", x % 8);
printf("x & 7 = %d (faster)\n\n", x & 7);
// Check even/odd
printf("Is x even? ");
if ((x & 1) == 0) {
printf("Yes (using bitwise)\n");
}
return 0;
}
Benchmark Example
#include <stdio.h>
#include <time.h>
int main() {
const int iterations = 10000000;
clock_t start, end;
double cpu_time_used;
volatile int result = 0;
printf("=== Performance Benchmark ===\n\n");
// Multiplication
start = clock();
for (int i = 0; i < iterations; i++) {
result = i * 8;
}
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Multiplication: %.3f seconds\n", cpu_time_used);
// Shift
start = clock();
for (int i = 0; i < iterations; i++) {
result = i << 3;
}
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("Shift: %.3f seconds (faster)\n", cpu_time_used);
return 0;
}
Advanced Examples
1. Complex Number Arithmetic
#include <stdio.h>
#include <complex.h>
int main() {
double complex z1 = 1.0 + 2.0 * I;
double complex z2 = 2.0 + 3.0 * I;
printf("z1 = %.2f + %.2fi\n", creal(z1), cimag(z1));
printf("z2 = %.2f + %.2fi\n\n", creal(z2), cimag(z2));
double complex sum = z1 + z2;
double complex diff = z1 - z2;
double complex prod = z1 * z2;
double complex quot = z1 / z2;
printf("Sum: %.2f + %.2fi\n", creal(sum), cimag(sum));
printf("Difference: %.2f + %.2fi\n", creal(diff), cimag(diff));
printf("Product: %.2f + %.2fi\n", creal(prod), cimag(prod));
printf("Quotient: %.2f + %.2fi\n", creal(quot), cimag(quot));
return 0;
}
2. Matrix Multiplication
#include <stdio.h>
#define SIZE 3
void matrix_multiply(int a[SIZE][SIZE], int b[SIZE][SIZE], int result[SIZE][SIZE]) {
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
result[i][j] = 0;
for (int k = 0; k < SIZE; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
}
void print_matrix(int matrix[SIZE][SIZE], char *name) {
printf("%s:\n", name);
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
printf("%4d ", matrix[i][j]);
}
printf("\n");
}
printf("\n");
}
int main() {
int a[SIZE][SIZE] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int b[SIZE][SIZE] = {
{9, 8, 7},
{6, 5, 4},
{3, 2, 1}
};
int result[SIZE][SIZE];
print_matrix(a, "Matrix A");
print_matrix(b, "Matrix B");
matrix_multiply(a, b, result);
print_matrix(result, "A × B");
return 0;
}
Best Practices Summary
Do's and Don'ts
// DO: Use parentheses for complex expressions
int result = (a + b) * (c - d);
// DON'T: Rely on operator precedence
int wrong = a + b * c - d; // Confusing
// DO: Check for overflow
if (a > INT_MAX - b) {
printf("Overflow would occur\n");
}
// DON'T: Ignore overflow
int dangerous = a + b; // May overflow silently
// DO: Use explicit casts for mixed types
float result = (float)a / b;
// DON'T: Mix types without understanding
float wrong = a / b; // Integer division first!
// DO: Use bitwise ops for performance when appropriate
int multiplied = x << 3; // x * 8
// DON'T: Use bitwise ops for readability
int confusing = x << 3; // Is this multiplication or shift?
Conclusion
This comprehensive guide covers all aspects of arithmetic operations in C:
Key Takeaways
- Basic operators (+, -, *, /, %) for fundamental arithmetic
- Operator precedence determines evaluation order
- Integer vs floating-point division behaves differently
- Type conversion affects calculation results
- Overflow/underflow can cause subtle bugs
- Bitwise operations provide low-level control
- Math library offers advanced functions
- Performance considerations matter for critical code
Best Practices
- Always consider type sizes and overflow
- Use parentheses for clarity
- Be careful with integer division
- Avoid comparing floating-point directly
- Use bitwise operations for performance when appropriate
- Test edge cases (zero, negative numbers, large values)
Mastering these concepts is essential for writing correct, efficient C programs.