Tutorials Logic, IN info@tutorialslogic.com

C Data Types, Sizes, Limits, and Conversions

Primary Data Types

A C type controls a value's representation, valid operations, and minimum supported range. Except for char occupying exactly one C byte, the language does not promise one universal byte size for the basic types.

Use int for ordinary arithmetic, size_t for object sizes, and an exact-width type such as uint32_t only when a protocol, file format, or hardware interface requires that width.

C provides integer, floating-point, character, Boolean, and void types. The table shows a common modern implementation, not a language guarantee; inspect your compiler with sizeof, <limits.h>, and <float.h>.

Type Common Size Format Specifier Range Description
int 4 bytes %d or %i At least -32,767 to 32,767 Integer numbers
float 4 bytes %f At least six decimal digits of precision Single-precision decimal
double 8 bytes %lf At least ten decimal digits of precision Double-precision decimal
char 1 byte %c Signedness is implementation-defined Single character
void - - - No value (used for functions/pointers)

Type Modifiers

The signed, unsigned, short, and long modifiers change a numeric type. Their exact widths still depend on the implementation, but C guarantees the ordering sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long).

Type Size Format Specifier Range
short int 2 bytes %hd -32,768 to 32,767
unsigned int 4 bytes %u 0 to 4,294,967,295
long int 4 or 8 bytes %ld -2,147,483,648 to 2,147,483,647 (min)
long long int 8 bytes %lld -9.2 x 10^18 to 9.2 x 10^18
unsigned long long 8 bytes %llu 0 to 1.8 x 10^19
unsigned char 1 byte %c 0 to 255
long double 10 or 16 bytes %Lf Extended precision

Derived Types

C also has derived data types that are built from primary types:

  • Arrays - collection of elements of the same type
  • Pointers - variables that store memory addresses
  • Structures - group of variables of different types under one name
  • Unions - similar to structures but share the same memory
  • Functions - blocks of reusable code

Declaring and Printing All Data Types

Declaring and Printing All Data Types
#include <stdio.h>

int main() {
    int    age    = 25;
    float  price  = 9.99f;
    double pi     = 3.14159265358979;
    char   grade  = 'A';

    printf("int:    %d\n",  age);
    printf("float:  %f\n",  price);
    printf("double: %lf\n", pi);
    printf("char:   %c\n",  grade);

    // Printing char as integer (ASCII value)
    printf("char as int: %d\n", grade);  // 65

    return 0;
}

/*
Output:
int:    25
float:  9.990000
double: 3.141593
char:   A
char as int: 65
*/

sizeof Operator and Type Modifiers

sizeof Operator and Type Modifiers
#include <stdio.h>

int main() {
    // sizeof returns the size in bytes
    printf("Size of char:           %zu bytes\n", sizeof(char));
    printf("Size of int:            %zu bytes\n", sizeof(int));
    printf("Size of float:          %zu bytes\n", sizeof(float));
    printf("Size of double:         %zu bytes\n", sizeof(double));
    printf("Size of long int:       %zu bytes\n", sizeof(long int));
    printf("Size of long long int:  %zu bytes\n", sizeof(long long int));
    printf("Size of unsigned int:   %zu bytes\n", sizeof(unsigned int));

    // Type modifiers in action
    unsigned int  population = 4294967295U;  // max unsigned int
    long long int bigNum     = 9223372036854775807LL;
    short int     small      = 32767;

    printf("\nunsigned int:   %u\n",   population);
    printf("long long int:  %lld\n",  bigNum);
    printf("short int:      %hd\n",   small);

    return 0;
}

/*
Output (64-bit system):
Size of char:           1 bytes
Size of int:            4 bytes
Size of float:          4 bytes
Size of double:         8 bytes
Size of long int:       8 bytes
Size of long long int:  8 bytes
Size of unsigned int:   4 bytes
*/

Limits and Widths

Use <limits.h> for integer limits, <float.h> for floating characteristics, and sizeof for the active implementation. <stdint.h> supplies exact-width types only when the implementation supports them; int_least32_t and int_fast32_t express minimum width or preferred speed instead.

  • sizeof returns size_t, so print it with %zu.
  • CHAR_BIT reports the number of bits in one C byte.
  • Use the PRI macros from <inttypes.h> when printing fixed-width integers.
  • Plain char is distinct from signed char and unsigned char.

Arithmetic Conversions

Small integer types are promoted before most arithmetic. The usual arithmetic conversions then choose a common type for mixed operands. A negative int compared directly with size_t may become a very large unsigned value, so prove the value is nonnegative before converting.

Narrowing an integer can change its value. Converting an out-of-range floating value to an integer is undefined, while large integers converted to floating point may lose precision. Validate the destination range before a conversion that can discard information.

Safe Index Comparison

Safe Index Comparison
#include <stddef.h>\n#include <stdio.h>\n\nint main(void) {\n    int index = -1;\n    size_t count = 4;\n\n    if (index >= 0 && (size_t) index < count) {\n        puts("valid index");\n    } else {\n        puts("invalid index");\n    }\n}
Output
invalid index

The first condition proves that converting index to size_t cannot turn a negative value into a huge unsigned value.

Type Selection

Need Starting Type Reason
Ordinary arithmetic int Natural integer operations on the target.
Object size or element count size_t Matches sizeof and library size parameters.
Pointer difference ptrdiff_t Represents valid pointer subtraction.
Exactly 32 protocol bits uint32_t Expresses an external width when available.
Decimal money Checked scaled integer Avoids binary floating-point rounding of decimal units.
Before you move on

Portable Type Review

4 checks
  • The chosen type expresses the value domain rather than an assumed machine size.
  • Every conversion that can lose range or precision is checked.
  • Formatted I/O specifiers match their promoted argument types.
  • Compiler warnings are enabled and reviewed.

Type Bugs

  • Hard-coded byte size

    Use sizeof and the implementation limit macros.
  • Wrong printf specifier

    Match the promoted argument type and enable compiler warnings.
  • Unsigned countdown underflow

    Write the loop so zero terminates before decrement wraps.
  • Unchecked narrowing cast

    Compare against the destination limits before converting.

Try this next

Test Type Boundaries

0 of 2 completed

  1. Print the sizes and limits of the numeric types on your compiler. Use sizeof, <limits.h>, and <float.h>.
  2. Convert a long value to int only when it fits. Compare with INT_MIN and INT_MAX before casting.
Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.