C
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
108: Complex Number Arithmetic with complex.h
I've noticed a recurring pattern when developers first tackle complex numbers in C: they immediately reach for a struct. They'll define a typedef struct { double real; double imag; } Complex; and then spend an hour writing helper functions like complex_add() and complex_multiply(). It feels natural because that's how you'd model a data object, but in C, doing this is actually fighting against the language.
You don't need a custom struct for complex math
The problem with the struct approach is that you lose the ability to use standard mathematical operators. If you use a struct, you can't just write z = a + b;. You're stuck with verbose function calls that make your formulas unreadable. C99 introduced complex.h to fix this, treating complex numbers as a first-class numeric type.
// The "Wrong" way (Manual Structs)
typedef struct { double r, i; } Complex;
Complex add(Complex a, Complex b) {
return (Complex){a.r + b.r, a.i + b.i};
}
// The C way (complex.h)
#include
double complex a = 1.0 + 2.0 * I;
double complex b = 3.0 + 4.0 * I;
double complex z = a + b; // This actually works!
In the second example, the compiler knows exactly how to handle the addition. It's cleaner, faster, and looks like the math you saw in a textbook.
Letting the compiler handle the imaginary unit
You'll notice I used I in the example above. This isn't a variable I declared; it's a macro defined in complex.h that represents the imaginary unit $\sqrt{-1}$. When you multiply a real number by I, the compiler treats the result as a complex type.
I should warn you: if you're coming from a language like Python, you might be tempted to try and access the real and imaginary parts using dot notation (like z.real). That won't work here. Because double complex is a built-in type and not a struct, you have to use specific accessor functions.
Extracting components and calculating magnitude
To get the individual pieces of a complex number back out, use creal() and cimag(). If you need the magnitude (the distance from the origin in the complex plane), cabs() is your friend. This is much better than manually typing sqrt(r*r + i*i) every time you need a length.
#include
#include
int main() {
double complex z = 3.0 + 4.0 * I;
printf("Real part: %f\n", creal(z)); // 3.0
printf("Imaginary part: %f\n", cimag(z)); // 4.0
printf("Magnitude: %f\n", cabs(z)); // 5.0
return 0;
}
One quick tip: if you're working with float or long double, use the corresponding versions: float complex with crealf(), or long double complex with creall(). Stick to double complex unless you have a very specific memory or precision requirement.
📋 Practical Task
Implementing a Basic Phasor Addition Tool for AC Circuits
In electrical engineering, AC voltages are often represented as "phasors" (complex numbers). Your task is to write a program that calculates the total voltage of two AC sources connected in series.
- Define two complex numbers representing voltages:
V1 = 120.0 + 30.0IV2 = 80.0 - 10.0I
- Calculate the total voltage
V_total = V1 + V2. - Calculate the magnitude of the total voltage using
cabs(). - Print the resulting total voltage in the format:
Total Voltage: (real + imag I), Magnitude: mag.
Constraint: You must use double complex and the complex.h library. Do not define any custom structs.
There are no comments for now.