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.

The - token in C functions as an overloaded operator representing either binary subtraction or unary arithmetic negation, depending on its lexical context and arity.

Binary Subtraction Operator

When used as a binary operator, - computes the difference between its left and right operands. It evaluates with left-to-right associativity.
#include <stdio.h>
#include <stddef.h>

int main(void) {
    int a = 10;
    int b = 3;
    int diff = a - b;
    printf("Integer difference: %d\n", diff);

    int array[5] = {0};
    int *ptr_high = &array[4];
    int *ptr_low = &array[1];
    
    /* Pointer subtraction */
    ptrdiff_t ptr_diff = ptr_high - ptr_low;
    printf("Pointer difference: %td\n", ptr_diff);
    
    /* Pointer and integer subtraction */
    int *ptr_offset = ptr_high - 2;
    printf("Pointer offset difference: %td\n", ptr_high - ptr_offset);

    return 0;
}
Operand Constraints and Semantics:
  • Arithmetic Types: If both operands have arithmetic types (integer or floating-point), the compiler applies the usual arithmetic conversions to establish a common real type before performing the subtraction.
  • Unsigned Integer Subtraction: If the common type is an unsigned integer, the operation follows modulo arithmetic. Subtracting a larger value from a smaller value does not overflow; instead, it wraps around to a well-defined positive value (modulo 2^N, where N is the number of bits in the type).
  • Signed Integer Overflow: If the operands are of signed integer types and the mathematically correct result cannot be represented in the resulting type (e.g., INT_MIN - 1), the operation invokes undefined behavior.
  • Pointer and Integer: If the left operand is a pointer to a complete object type and the right operand is an integer type, the integer is scaled by the sizeof the pointed-to type. The result is a pointer of the same type as the original pointer, representing a memory address offset by that many elements. Subtracting a positive integer shifts the pointer to a lower address, whereas subtracting a negative integer shifts it to a higher address. Incomplete types (like void or arrays of unknown size) are strictly prohibited.
  • Pointer and Pointer: If both operands are pointers to compatible complete object types (ignoring qualifiers), the operation yields the distance between them in terms of array elements. The result is a signed integer of type ptrdiff_t (defined in <stddef.h>). The behavior is undefined if the pointers do not point to elements within the same array object (or one past the last element).

Unary Minus Operator

When used as a unary operator, - computes the arithmetic negation of its single operand. It evaluates with right-to-left associativity.
#include <stdio.h>

int main(void) {
    int val = 5;
    int neg_val = -val;
    printf("Negated int: %d\n", neg_val);

    unsigned char uc_val = 5;
    int neg_uc = -uc_val;
    printf("Negated unsigned char: %d\n", neg_uc);

    unsigned char uc_zero = 0;
    int neg_zero = -uc_zero;
    printf("Negated unsigned char zero: %d\n", neg_zero);

    double f_val = 3.14;
    double neg_f = -f_val;
    printf("Negated double: %f\n", neg_f);

    return 0;
}
Operand Constraints and Semantics:
  • Arithmetic Types: The operand must have an arithmetic type.
  • Integer Promotion and Semantics: The compiler performs integer promotions on integer operands before the operation. The type of the result is the type of the promoted operand.
    • Narrow Unsigned Types: Due to value-preserving promotion rules, narrow unsigned types (like unsigned char or unsigned short) are promoted to signed int (assuming int can represent all their values). Applying - yields the arithmetic negation of the promoted value as a signed int. For example, -(unsigned char)5 evaluates to -5 of type int, while -(unsigned char)0 evaluates to 0 of type int.
    • Unsigned Types: If the promoted type is unsigned, the result is computed by subtracting the promoted value from the maximum value of the promoted unsigned type plus one, resulting in well-defined modulo wrap-around.
    • Signed Types: For signed integers, this computes the arithmetic negative of the value. If the operand’s value is the minimum representable value for that type (e.g., -INT_MIN in a two’s complement system), the mathematically correct positive result cannot be represented, invoking undefined behavior due to signed integer overflow.
  • Floating-Point Semantics: For floating-point types, the unary - operator produces the arithmetic negative of the operand. The core C standard does not mandate strict sign-bit inversion unless the implementation explicitly conforms to IEEE 754 (IEC 60559) via Annex F, in which case specific behaviors for -0.0, infinities, and NaN payloads apply.

Precedence

The two forms of the - operator occupy different levels in the C precedence table:
  1. Unary - has high precedence (Level 2), sharing its level with other unary operators like ++, --, !, ~, * (dereference), and & (address-of).
  2. Binary - has lower precedence (Level 4), sharing its level strictly with the binary addition operator +.
Master C with Deep Grasping Methodology!Learn More