Table of Contents

<complex.h>

In C programming language, <complex.h> is a header which is part of the C standard library (specifically, C99). It implements the algebra of complex numbers $\mathbb C$.

You need at least version C99 to use this header, so compile with gcc -std=c99 main.c -o program.

Usage

Here's an example that creates a complex number $2 + i3$

// Compile: gcc -std=c99 main.c -o program
// Run:     ./program
// Output:  Complex number 'z' equals to '2 + i3'
#include <complex.h>
 
int main()
{
    const double complex z = 2 + I * 3;
    printf("Complex number 'z' equals to '%g + i%g'", creal(z), cimag(z));
    return 0;
}

This syntax surprised me the first time I saw it. How exactly does including a header like <complex.h> give double the ability to become double complex? Can a header really add new syntax to C programming language?

Well, no. In fact, C99 has a keyword called _Complex already, which you can use even without including <complex.h>. This is why I using version C99 is important if you want to use this header! In traditional C programming language (a.k.a. C89), there is no _Complex keyword.

// Compile: gcc -std=c99 main.c -o program
// Run:     ./program
// Output:  none
/* #include <complex.h> */
 
int main()
{
    float _Complex z {2, 3};        // most commonly 32bit
    double _Complex z {2, 3};       // most commonly 64bit
    long double _Complex z {2, 3};  // most commonly 128bit
    return 0;
}

What <complex.h> header actually does is:

One, it provides a macro #define I _Complex_I for the imaginary unit $i$. For example $z = 2 + i3$ is written as double complex z = 2 + I * 3. Macros I and _Complex_I are just a short hand for (double _Complex){0, 1}.

Two, it provides a myriad of functions prefixed by the character 'c' such as cabs(z), cexp(z), clog(z), csin(z), ccos(z), ctan(z), … These implement complex functions $|z|$, $e^z$, $\log(z)$, $\sin(z)$, $\cos(z)$, $\tan(z)$. You will need to link the standard math library with -lm to use these! The -lm option tells the linker to link libm.so library, which is located in /usr/lib

So, the following is likely how you want to compile your program with GCC, if you want to use complex numbers:

gcc -lm -std=c99 main.c -o main

Illustration

The following example illustrates most (though not all) of the header's capabilities. You can extend the example by adding more C_PRINT(...) calls!

// Compile: gcc -std=c99 main.c -o main
// Execute:./main
/*
         z =  2 + i3
         w =  1 + i4
     z + w =  3 + i7
     z - w =  1 - i1
     z * w = -10 + i11
     z / w =  0.823529 - i0.294118
  creal(z) =  2 - i0
  cimag(z) =  3 - i0
   cabs(z) =  3.60555 - i0
   carg(z) =  0.982794 - i0
*/
#include <stdio.h>
#include <complex.h>
#include <math.h>
 
#define C_PRINT(z) \
    do { \
        double real = creal((z)); \
        double imag = cimag((z)); \
        char *sign_1 = real > 0 ? " " : "-"; \
        char *sign_2 = imag > 0 ? "+" : "-"; \
        printf(("%10s = %s%g %s i%g\n"), (#z), sign_1, fabs(real), sign_2, fabs(imag)); \
    } while (0)
 
 
int main()
{
    double complex z = 2.0 + I * 3.0;
    double complex w = 1.0 + I * 4.0;
    C_PRINT(z);
    C_PRINT(w);
    C_PRINT(z + w);
    C_PRINT(z - w);
    C_PRINT(z * w);
    C_PRINT(z / w);
    C_PRINT(creal(z));
    C_PRINT(cimag(z));
    C_PRINT(cabs(z));
    C_PRINT(carg(z));
    return 0;
}