Arithmetic Operations in C: Complete Guide

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

OperatorNameDescriptionExample
+AdditionAdds two operandsa + b
-SubtractionSubtracts second operand from firsta - b
*MultiplicationMultiplies two operandsa * b
/DivisionDivides first operand by seconda / b
%ModulusReturns remainder of divisiona % 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)

LevelOperatorDescriptionAssociativity
1()ParenthesesLeft to Right
2++ --Postfix increment/decrementLeft to Right
3++ -- + - ! ~Unary operatorsRight to Left
4* / %MultiplicativeLeft to Right
5+ -AdditiveLeft to Right
6<< >>Bitwise shiftLeft to Right
7< <= > >=RelationalLeft to Right
8== !=EqualityLeft to Right
9&Bitwise ANDLeft to Right
10^Bitwise XORLeft to Right
11|Bitwise ORLeft to Right
12&&Logical ANDLeft to Right
13||Logical ORLeft to Right
14?:Ternary conditionalRight to Left
15= += -= etc.AssignmentRight to Left
16,CommaLeft 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

OperatorExampleEquivalent to
+=a += ba = a + b
-=a -= ba = a - b
*=a *= ba = a * b
/=a /= ba = a / b
%=a %= ba = 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

OperatorNameDescription
&ANDBitwise AND
|ORBitwise OR
^XORBitwise XOR
~NOTBitwise complement
<<Left shiftShift bits left
>>Right shiftShift 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

  1. Always consider type sizes and overflow
  2. Use parentheses for clarity
  3. Be careful with integer division
  4. Avoid comparing floating-point directly
  5. Use bitwise operations for performance when appropriate
  6. Test edge cases (zero, negative numbers, large values)

Mastering these concepts is essential for writing correct, efficient C programs.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper