Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

C Language Dictionary

  1. Home
  2. C Language Dictionary
  3. unsigned / signed / const / volatile

unsigned / signed / const / volatile

Since: C89(1989)

Type qualifiers are keywords added to basic types to change the behavior of a variable. They include unsigned/signed for controlling whether a value can be negative, const for preventing a value from being changed, and volatile for controlling compiler optimization.

Syntax

unsigned int variableName;
unsigned char variableName;

// Declares a signed integer type (can hold negative values). This is the default.
signed int variableName;

// Declares a constant whose value cannot be changed.
const type variableName = value;

// Suppresses compiler optimization for this variable.
volatile type variableName;

// You can also combine multiple qualifiers.
const unsigned int variableName = value;

Type Qualifier List

QualifierDescription
unsignedMakes the integer type unsigned. It cannot hold negative values, but the upper limit for positive values is roughly doubled. For example, unsigned int can hold values from 0 to 4294967295.
signedMakes the integer type signed. This is the default behavior and is usually omitted, but it can be specified explicitly for char, whose signedness varies by implementation.
constDeclares a variable as a constant. It must be initialized at the time of declaration, and its value cannot be assigned or changed afterward.
volatileSuppresses compiler optimization. Use this for variables whose values may change from outside the program, such as interrupt handlers or hardware registers.

Sample Code

sample_unsigned_const.c
#include <stdio.h>

int main(void) {
    /* The 'u' suffix marks an unsigned integer constant. */
    unsigned int population = 1280000000u;
    printf("Population: %u\n", population);

    unsigned char byte = 255;
    printf("Byte value: %u\n", byte);

    /* Unsigned types wrap around: 0 - 1 becomes the maximum value. */
    unsigned int u = 0;
    u = u - 1;
    printf("unsigned wraparound: %u\n", u);

    const double PI = 3.14159265358979;
    const int MAX_SIZE = 100;
    printf("Pi: %f\n", PI);
    printf("Max size: %d\n", MAX_SIZE);
    /* PI = 3.0; */ /* Compile error — const cannot be reassigned. */

    /* volatile prevents the compiler from caching this variable. */
    volatile int sensor_value = 0;
    printf("Sensor value: %d\n", sensor_value);

    /* const volatile is used for read-only hardware registers. */
    /* const volatile int *reg = (int *)0x40000000; */

    return 0;
}

Run the following command:

gcc unsigned_const.c -o unsigned_const
./unsigned_const
Population: 1280000000
Byte value: 255
unsigned wraparound: 4294967295
Pi: 3.141593
Max size: 100
Sensor value: 0

const Pointer and Buffer Protection

Combining const with a pointer tells the compiler that the pointed-to data will not be modified — a common pattern for read-only function parameters.

const_pointer.c
#include <stdio.h>

/* const char *: the string pointed to will not be modified. */
int count_char(const char *s, char c) {
    int n = 0;
    for (; *s; s++) {
        if (*s == c) n++;
    }
    return n;
}

int main(void) {
    const char *msg = "Son Goku is the strongest.";
    printf("Count of 'o': %d\n", count_char(msg, 'o'));
    printf("Count of 's': %d\n", count_char(msg, 's'));

    /* const array elements cannot be assigned. */
    const int scores[] = {95, 88, 72, 100};
    /* scores[0] = 0; */ /* Compile error */

    int total = 0;
    for (int i = 0; i < 4; i++) {
        total += scores[i];
    }
    printf("Total: %d\n", total);

    return 0;
}

Run the following command:

gcc const_pointer.c -o const_pointer
./const_pointer
Count of 'o': 3
Count of 's': 2
Total: 355

Common Mistakes

Common Mistake: Mixing Signed and Unsigned Types

When a signed value is compared or computed with an unsigned value, the signed side is converted to unsigned, producing unexpected results.

unsigned_signed_ng.c
#include <stdio.h>

int main(void) {
    unsigned int u = 1;
    int s = -1;

    /* OK: cast to the same type first */
    if (s < (int)u) {
        printf("OK: compared after casting\n");
    }

    /* Show what happens without casting */
    if ((unsigned int)s > u) {
        /* (unsigned int)(-1) == 4294967295, which is > 1 */
        printf("As unsigned, -1 becomes: %u\n", (unsigned int)s);
    }

    /* OK: compare using the same type */
    int ui = (int)u;
    if (s < ui) {
        printf("OK: same-type comparison (%d < %d)\n", s, ui);
    }

    return 0;
}

Run the following command:

gcc unsigned_signed_ng.c -o unsigned_signed_ng
./unsigned_signed_ng
OK: compared after casting
As unsigned, -1 becomes: 4294967295
OK: same-type comparison (-1 < 1)

Notes

The unsigned type extends the range of positive values by not supporting negative numbers. Mixing signed and unsigned types in arithmetic can produce unexpected results. Unsigned types also take precedence in comparison operations, so extra care is required.

const tells the compiler that a value will not be changed, allowing invalid assignments to be caught at compile time. It provides better type checking than macro-based constants using #define, so using const is recommended in C99 and later. For more on macros, see #include / #define (Constants).

volatile is important in hardware control and embedded programming. Compilers may apply optimizations such as register caching, but these optimizations can cause incorrect behavior for variables whose values may change externally. You can check the actual size of each type using sizeof.

If you find any errors or copyright issues, please .