Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

_Complex is a built-in type specifier introduced in C99 used to declare variables that represent complex numbers. It modifies standard floating-point types to allocate contiguous memory for both a real and an imaginary component within a single scalar variable.

Type Variants

The _Complex keyword is not a standalone type. It must be explicitly combined with one of the three standard floating-point type specifiers to form a valid type. The C standard does not mandate specific bit-widths or representations (such as IEEE 754) for these underlying types.
float _Complex z_float;             // Two floats
double _Complex z_double;           // Two doubles
long double _Complex z_long_double; // Two long doubles

The <complex.h> Header

While _Complex is a native compiler keyword, standard C practice utilizes the <complex.h> header. This header provides the complex macro (which expands to _Complex) and the I macro. According to the C standard, I expands to either _Complex_I or _Imaginary_I. It evaluates to a constant expression of type const float _Complex only if the implementation expands it to _Complex_I. If the compiler supports pure imaginary types, it expands to _Imaginary_I, which has the type const float _Imaginary.
#include <stdio.h>
#include <complex.h>

int main(void) {
    // 'complex' is a macro for '_Complex'
    double complex z = 3.0 + 4.0 * I; 
    
    printf("z = %.1f + %.1fi\n", creal(z), cimag(z));
    return 0;
}

Memory Layout and Alignment

The C standard guarantees that the memory layout and alignment of a _Complex type are strictly equivalent to an array of two elements of the corresponding real floating-point type.
  • Index 0: The real component.
  • Index 1: The imaginary component.
Because of this strict layout guarantee, it is safe to cast a pointer to a _Complex type into a pointer to its underlying real type to access the components directly.
#include <stdio.h>
#include <complex.h>

int main(void) {
    double _Complex z = 5.0 + 2.0 * I;

    // Valid and strictly conforming memory access
    double *ptr = (double *)&z;
    double real_part = ptr[0]; 
    double imag_part = ptr[1]; 

    printf("Real: %.1f, Imaginary: %.1f\n", real_part, imag_part);
    return 0;
}

Component Access and Initialization

While the I macro allows for algebraic initialization, C11 introduced the CMPLX, CMPLXF, and CMPLXL macros to construct complex numbers safely, avoiding edge cases with floating-point environments (like NaN or signed zeros). To extract components without pointer casting, the <complex.h> header provides strictly typed functions. For example, creal() and cimag() take a double complex argument and return a double. Corresponding functions exist for float (crealf(), cimagf()) and long double (creall(), cimagl()). True type-generic macros for complex numbers are provided separately by the <tgmath.h> header.
#include <stdio.h>
#include <complex.h>

int main(void) {
    // C11 standard initialization
    double complex z = CMPLX(0.0, -1.0);

    // Strictly typed component extraction
    double r = creal(z); // Takes double complex, returns double
    double i = cimag(z); // Takes double complex, returns double

    printf("r = %.1f, i = %.1f\n", r, i);
    return 0;
}

Native Arithmetic

The C standard explicitly defines the semantics and behavior of standard arithmetic operators (+, -, *, /) and assignment operators (+=, -=, *=, /=) when applied to _Complex types. The compiler automatically generates the underlying instructions to handle complex arithmetic rules (e.g., cross-multiplication for the * operator).
#include <stdio.h>
#include <complex.h>

int main(void) {
    double _Complex z1 = 1.0 + 2.0 * I;
    double _Complex z2 = 3.0 - 4.0 * I;

    double _Complex sum = z1 + z2; 
    double _Complex prd = z1 * z2; 

    printf("Sum: %.1f %+.1fi\n", creal(sum), cimag(sum));
    printf("Product: %.1f %+.1fi\n", creal(prd), cimag(prd));
    return 0;
}
Master C with Deep Grasping Methodology!Learn More