Back to C Programming
2026-04-188 min read

arithmetic types defined by the language

Learn arithmetic types defined by the language step by step with clear examples and exercises.

Why This Matters

Understanding arithmetic types is crucial for any C programmer as they form the backbone of numerical computations. Knowing the differences between various data types helps optimize code performance, avoid common pitfalls that can lead to bugs or incorrect results, and make your programs more efficient. In addition, a solid grasp of these concepts will be beneficial during exams, interviews, and when debugging real-world issues.

Prerequisites

Before diving into the core concept, it's essential to have a basic understanding of:

  1. C programming basics (variables, operators, expressions)
  2. Data structures (arrays, pointers)
  3. Control structures (if-else, loops)
  4. Functions and function prototypes
  5. Basic input/output operations (printf(), scanf())
  6. Memory management concepts (malloc(), free())
  7. Structures and unions
  8. Preprocessor directives (#include, #define)
  9. Understanding of basic mathematical operations and their order of precedence
  10. Familiarity with conditional and loop statements
  11. Basic knowledge of bitwise operators

Core Concept

Arithmetic types in C include:

  1. Boolean type
  2. Character types
  3. Integer types
  4. Real floating types
  5. Complex floating types
  6. Imaginary floating types

Let's explore each of these data types and their properties in detail.

Boolean Type

The Boolean type in C can hold one of two values: 1 (true) or 0 (false). It is represented by the _Bool type (until C23) or the built-in bool type (since C23). The conversion to _Bool (until C23) or bool (since C23) does not work the same as conversion to other integer types. For example, (bool) 0.5 evaluates to true, while (int) 0.5 evaluates to 0.

Character Types

C offers several character types:

  1. signed char - used for signed character representation.
  2. unsigned char - used for unsigned character representation and also used to inspect object representations (raw memory).
  3. char - used for character representation. It is equivalent to either signed char or unsigned char, but it is a distinct type, different from both.
  4. Wide characters are defined by the standard library as:
  • wchar_t (since C11)
  • char16_t and char32_t (since C11) for representing wide characters
  • char8_t (since C23) for UTF-8 characters

Integer Types

C provides several integer types, each with a specific size and range of values. The most commonly used are:

  1. short int (also accessible as short, may use the keyword signed) - used for short integers that require less memory than regular integers.
  2. unsigned short int (also accessible as unsigned short) - used for unsigned short integers, implementing modulo arithmetic and suitable for bit manipulations.
  3. int (also accessible as signed int) - this is the most optimal integer type for the platform, and it is guaranteed to be at least 16 bits. Most current systems use 32 bits.
  4. unsigned int (also accessible as unsigned) - the unsigned counterpart of int, implementing modulo arithmetic. Suitable for bit manipulations.
  5. long int (also accessible as long) - used for long integers, which require more memory than regular integers.
  6. unsigned long int (also accessible as unsigned long) - used for unsigned long integers, which require more memory than regular unsigned integers.
  7. long long int (also accessible as lon) - used for even larger integers that require still more memory.

Worked Example

Let's consider a simple example demonstrating the use of various arithmetic types in C:

#include <stdio.h>

int main() {
char c = 'A'; // Character type
unsigned int ui = 255; // Unsigned integer type
long long int lli = 9223372036854775807LL; // Long long integer type
float f = 3.14f; // Real floating type
double d = 3.14159265358979323846; // Double precision floating type

printf("Character: %c\n", c);
printf("Unsigned integer: %u\n", ui);
printf("Long long integer: %lld\n", lli);
printf("Float: %.2f\n", f);
printf("Double: %.17Lf\n", d);

return 0;
}

In this example, we declare variables of various arithmetic types and print their values using the printf() function. The output will be:

Character: A
Unsigned integer: 255
Long long integer: 9223372036854775807
Float: 3.14
Double: 3.141592653589793

Common Mistakes

  1. Forgetting to include the necessary header files (e.g., `) for using functions like printf()`.
  2. Incorrectly using integer literals without a suffix (e.g., using 5 instead of 5u or 5l for unsigned and long integers, respectively).
  3. Assuming that the size and range of integer types are consistent across all platforms.
  4. Converting floating-point numbers to Boolean types incorrectly, leading to unexpected results (e.g., assuming that (bool) 0.5 will evaluate to false).
  5. Misunderstanding the difference between signed and unsigned integer types and their range of values.
  6. Neglecting to handle overflow and underflow errors when performing arithmetic operations with large integer values.
  7. Failing to understand the differences between character types (e.g., char, signed char, unsigned char) and their usage in various scenarios.
  8. Incorrectly using bit manipulation techniques, leading to unexpected results or logic errors.
  9. Not being aware of the existence and proper usage of wide characters (wchar_t, char16_t, char32_t, char8_t) for representing non-ASCII characters.
  10. Neglecting to check for integer overflow or underflow when performing arithmetic operations involving large values.
  11. Failing to consider the order of operations and precedence when writing complex expressions involving multiple operators.
  12. Misusing bitwise operators, leading to incorrect results or logic errors.
  13. Not understanding the differences between signed and unsigned integer types and their representation in binary format.
  14. Assuming that all platforms use the same number of bits for representing a given integer type.
  15. Neglecting to handle exceptions or errors when performing arithmetic operations with floating-point numbers, such as division by zero or overflow.
  16. Misunderstanding the differences between float and double precision floating types in terms of their range, precision, and memory usage.
  17. Not being aware of the existence and proper usage of complex and imaginary floating types for advanced mathematical computations.

Common Mistakes (subsections)

Integer Literals

  1. Incorrectly using integer literals without a suffix (e.g., using 5 instead of 5u or 5l for unsigned and long integers, respectively).
  2. Assuming that the size and range of integer types are consistent across all platforms.
  3. Neglecting to handle overflow and underflow errors when performing arithmetic operations with large integer values.
  4. Failing to understand the differences between character types (e.g., char, signed char, unsigned char) and their usage in various scenarios.
  5. Incorrectly using bit manipulation techniques, leading to unexpected results or logic errors.
  6. Not being aware of the existence and proper usage of wide characters (wchar_t, char16_t, char32_t, char8_t) for representing non-ASCII characters.
  7. Neglecting to check for integer overflow or underflow when performing arithmetic operations involving large values.
  8. Failing to consider the order of operations and precedence when writing complex expressions involving multiple operators.
  9. Misusing bitwise operators, leading to incorrect results or logic errors.
  10. Not understanding the differences between signed and unsigned integer types and their representation in binary format.
  11. Assuming that all platforms use the same number of bits for representing a given integer type.

Floating-Point Numbers

  1. Neglecting to handle exceptions or errors when performing arithmetic operations with floating-point numbers, such as division by zero or overflow.
  2. Misunderstanding the differences between float and double precision floating types in terms of their range, precision, and memory usage.
  3. Not being aware of the existence and proper usage of complex and imaginary floating types for advanced mathematical computations.

Practice Questions

  1. Write a program that calculates the factorial of a given number using various integer types (int, unsigned int, long long int) and compares their performance.
  2. Implement a function that checks if a given number is prime using bit manipulation techniques with unsigned int.
  3. Write a program that converts a decimal number to its binary, octal, and hexadecimal representations using unsigned char and printf().
  4. Implement a function that calculates the greatest common divisor (GCD) of two numbers using recursion with int.
  5. Write a program that sorts an array of integers using quicksort, and compare its performance with different integer types (int, unsigned int, long long int).
  6. Implement a function that calculates the power of a number using recursion with unsigned long long int.
  7. Write a program that converts a given string to uppercase or lowercase using bitwise operations with char.
  8. Implement a function that checks if two strings are anagrams using character arrays and sorting algorithms (e.g., bubble sort, quicksort).
  9. Write a program that calculates the Fibonacci sequence up to a given number using various integer types (int, unsigned int, long long int) and compares their performance.
  10. Implement a function that finds the largest prime factor of a given number using bit manipulation techniques with unsigned int.
  11. Write a program that calculates the sum of all numbers in an array using various integer types (int, unsigned int, long long int) and compares their performance.
  12. Implement a function that finds the smallest common multiple (SCM) of two numbers using recursion with int.
  13. Write a program that calculates the average of a set of numbers using various floating-point types (float, double) and compares their precision and performance.
  14. Implement a function that calculates the square root of a number using Newton's method with double.
  15. Write a program that finds the largest palindrome in a given range using various integer types (int, unsigned int, long long int) and compares their performance.
  16. Implement a function that calculates the sum of all prime numbers up to a given number using different methods (sieve of Eratosthenes, trial division) and compare their performance with various integer types (int, unsigned int, long long int).

FAQ

What is the difference between signed and unsigned integer types?

  • Signed integers can represent both positive and negative values, while unsigned integers only represent non-negative values.

Why should I use different integer types for numerical computations?

  • Using appropriate data types helps optimize code performance by minimizing memory usage and reducing the risk of overflow or underflow errors.

How can I convert a floating-point number to its equivalent Boolean value in C?

  • Convert the floating-point number to an integer using a cast, then compare it with zero (e.g., (bool)(my_float >= 0.5)).

What is the largest representable value for each integer type in C?

  • The largest representable values for various integer types are:
  • char: 127 or -128 (signed) and 255 (unsigned)
  • short int: 32767 or -32768 (signed) and 65535 (unsigned)
  • int: 2147483647 or -2147483648 (signed) and 4294967295 (unsigned)
  • long int