๐ฆ 4. Data Types in C
A data type describes the values a variable can hold and the operations that make sense for it. For example, a count uses an integer type, while a measurement may need a floating-point type. Choose a type that can represent the values your program needs.
A data type describes the kind of data associated with an object, expression, function return value, or other declaration in C.
For example:
int age = 20;
float price = 99.50f;
char grade = 'A';
The declarations tell the compiler that these objects have different types.
DATA TYPE
โ
โโโโโโโโโโผโโโโโโโโโ
โ โ โ
โผ โผ โผ
int float char
โ โ โ
โผ โผ โผ
20 99.5 A
The compiler uses types to interpret values and check operations. This also affects calculations: dividing two integers follows different rules from dividing floating-point values.
A program works with different kinds of information.
- whole numbers
- fractional values
- characters
- very large or very small numeric values
- addresses
- collections of related data
C needs a way to distinguish these different kinds of data.
int students = 60;
float temperature = 36.5f;
char section = 'A';
These objects represent different kinds of information and therefore use different types.
C TYPES โ โโโ Basic / Fundamental Types โ โโโ char โ โโโ signed integer types โ โโโ unsigned integer types โ โโโ _Bool โ โโโ float โ โโโ double โ โโโ long double โ โโโ void โ โโโ Derived Types โ โโโ Arrays โ โโโ Pointers โ โโโ Function types โ โโโ Structure Types โ โโโ Union Types โ โโโ Enumeration Types
Start with the basic types in this lesson. Later lessons explain arrays, pointers, functions, structures, unions, and enumerations.
| Type | Typical Use | Example |
|---|---|---|
char |
Character-sized integer type | 'A' |
short |
Short integer type | 100 |
int |
General-purpose integer | 500 |
long |
Integer type with at least as much range as int | 100000L |
long long |
Large integer values | 9000000000LL |
float |
Single-precision floating-point | 3.14f |
double |
Double-precision floating-point | 3.14159 |
long double |
Extended floating-point type | 3.14159L |
Many sizes and ranges depend on the compiler and target system. Treat a size shown by your own program as a result for that system, not a rule for every computer.
char Type
The char type is designed for character data and is
also an integer type in C.
char grade = 'A';
char symbol = '#';
Character constants use single quotation marks.
'A'
'B'
'7'
'@'
'A'
"A"
'A' is a character constant.
"A" is a string literal containing the
character A followed by a terminating null character.
Integer types represent whole-number values.
int count = 100;
short smallNumber = 25;
long population = 1000000L;
long long distance = 9000000000LL;
C provides several integer types because programs may need different ranges and storage requirements.
Can represent negative and non-negative values within its implementation-defined range.
Represents non-negative values and generally provides a larger non-negative range for the same width.
signed int temperature = -10;
unsigned int students = 500;
The unsigned keyword specifies that the type is
non-negative.
| Type | Can represent negative values? |
|---|---|
int |
Yes |
signed int |
Yes |
unsigned int |
No |
Unsigned types do not store negative values. Their arithmetic wraps within the typeโs range. Mixing signed and unsigned values can change comparisons or calculations, so check the conversion rules.
float Type
float is a floating-point type used for values
that may contain a fractional component.
float temperature = 36.5f;
float price = 99.99f;
The f suffix indicates a float
floating constant.
3.14f
Without the suffix:
3.14
the floating constant has type double.
double Type
double is a floating-point type that normally provides
more precision than float.
double pi = 3.141592653589793;
Floating-point types can approximate a wide range of values, but they cannot represent every decimal value exactly. For example, 0.1 is not exact in common binary floating-point formats.
Do not assume that every decimal value can be represented exactly in binary floating-point.
long double
long double is an extended floating-point type.
Its precision and representation are implementation-dependent.
long double value = 3.141592653589793238L;
The L suffix identifies a long double
floating constant.
_Bool Type
C provides the built-in integer type _Bool.
_Bool isPassed = 1;
In C99 through C17, the standard header <stdbool.h> provides the spelling bool and the
true and false macros. In C23, bool, true, and false are keywords.
#include <stdbool.h>
bool isPassed = true;
bool is provided by the standard header
<stdbool.h> in C99 through C17. The underlying type is
_Bool.
void Type
void represents the absence of a value or type
information in several C contexts.
A common example is a function that does not return a value:
void displayMessage(void)
{
printf("Hello");
}
A pointer to void, written void *,
is a separate concept and is useful for generic object pointers.
sizeof Operator
The sizeof operator determines the size in bytes
of a type or object.
#include <stdio.h>
int main(void)
{
printf("%zu\n", sizeof(int));
printf("%zu\n", sizeof(double));
printf("%zu\n", sizeof(char));
return 0;
}
sizeof(type)
โ
โผ
number of bytes
โ
โผ
depends on implementation
The result of sizeof has type
size_t, which is why %zu
is the appropriate printf conversion specifier in C99
and later.
A common beginner mistake is memorizing:
int = 4 bytes
char = 1 byte
float = 4 bytes
double = 8 bytes
These are common on many modern systems, but C does not require every implementation to use exactly those sizes.
The correct way to discover the size on the current implementation is:
sizeof(type)
C guarantees that sizeof(char) is exactly
1. A C byte is not required to contain exactly
8 bits; the number of bits in a byte is represented by
CHAR_BIT.
The header <limits.h> provides macros describing
limits of integer types on the current implementation.
#include <stdio.h>
#include <limits.h>
int main(void)
{
printf("INT_MIN = %d\n", INT_MIN);
printf("INT_MAX = %d\n", INT_MAX);
printf("UINT_MAX = %u\n", UINT_MAX);
return 0;
}
This is safer than assuming one universal numeric range.
The header <float.h> provides information
about the characteristics of floating-point types.
#include <stdio.h>
#include <float.h>
int main(void)
{
printf("FLT_DIG = %d\n", FLT_DIG);
printf("DBL_DIG = %d\n", DBL_DIG);
return 0;
}
For example, these values help you check how many decimal digits a floating-point type can preserve.
C provides keywords that combine with integer and floating types to describe different type forms.
| Keyword | Purpose |
|---|---|
signed |
Specifies a signed integer type. |
unsigned |
Specifies a non-negative integer type. |
short |
Specifies a short integer type. |
long |
Specifies a long integer or extended floating type. |
short int a;
unsigned int b;
long int c;
long long int d;
Integer types signed โ โโโ signed char โโโ short โโโ int โโโ long โโโ long long unsigned โ โโโ unsigned char โโโ unsigned short โโโ unsigned int โโโ unsigned long โโโ unsigned long long
The compiler and system determine the exact sizes and ranges. C still sets minimum requirements and rules for how the standard integer types relate to one another.
C provides three character types:
char
signed char
unsigned char
Whether plain char behaves as signed or unsigned
is implementation-defined.
Do not assume plain char is always signed
or always unsigned.
Integer literals can use suffixes to influence their type.
100
100U
100L
100UL
100LL
100ULL
| Literal | Meaning |
|---|---|
100 |
Integer constant without an explicit suffix |
100U |
Unsigned integer constant |
100L |
Long integer constant |
100LL |
Long long integer constant |
100ULL |
Unsigned long long integer constant |
3.14
3.14f
3.14L
| Literal | Type |
|---|---|
3.14 |
double |
3.14f |
float |
3.14L |
long double |
When different arithmetic types participate in an expression, C may convert values according to its conversion rules.
int a = 10;
double b = 2.5;
double result = a + b;
The integer value participates in the calculation after the appropriate conversion.
10 + 2.5
โ โ
โ โ
โโโโโโโโฌโโโโโโโโโโโโ
โผ
common arithmetic
conversion
โ
โผ
12.5
Type conversion is covered in greater depth when expressions and operators are introduced.
C applies the conversion automatically according to its type rules.
double x = 10;
The programmer requests a conversion using a cast.
double x = (double)10;
int a = 5;
int b = 2;
printf("%d\n", a / b);
Because both operands are integers, the division is integer
division and the result is 2.
Compare:
double result = 5.0 / 2.0;
Here the result is 2.5.
Data types can affect not only storage but also the behavior of expressions and operations.
C also supports derived and user-defined type constructs.
int numbers[5];
int *ptr;
struct Student
{
int roll;
};
Arrays, pointers, structures, unions, enumerations and function types will be studied separately.
| Requirement | Possible Choice |
|---|---|
| General whole number | int |
| Non-negative count | Appropriate unsigned integer type when justified |
| Character-sized data | char |
| Fractional value | float or double |
| Higher floating-point precision | double or long double, as appropriate |
| Boolean-style state | _Bool or bool with <stdbool.h> |
Choose a type by asking what values you need, whether fractions are required, and what calculations you will perform. Check the typeโs range instead of choosing it only because its size is small.
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int age = 21;
float height = 5.8f;
double percentage = 87.4567;
char grade = 'A';
bool passed = true;
printf("Age = %d\n", age);
printf("Height = %.1f\n", height);
printf("Percentage = %.4f\n", percentage);
printf("Grade = %c\n", grade);
printf("Passed = %d\n", passed);
return 0;
}
Program
โ
โโโ int
โ โโโ age
โ
โโโ float
โ โโโ height
โ
โโโ double
โ โโโ percentage
โ
โโโ char
โ โโโ grade
โ
โโโ bool
โ โโโ passed
โ
โโโ printf()
โโโ displays values
- Assuming every C compiler uses exactly the same type sizes.
-
Using
intfor a value that cannot fit in the required range. - Expecting integer division to produce a fractional result.
-
Confusing
charwith a string. -
Using the wrong
printf()format specifier. -
Assuming plain
charis always signed. - Treating floating-point values as if they were always exact decimal numbers.
printf() Format Specifiers
| Specifier | Common Use |
|---|---|
%d |
Signed decimal integer |
%u |
Unsigned decimal integer |
%c |
Character |
%f |
Floating-point output |
%zu |
size_t, commonly used with sizeof |
Match each format specifier to its argument. A function that accepts a varying number of arguments, such as printf()
cannot safely use a format specifier that expects the wrong argument type. A mismatch can cause undefined behaviour.
4.30 Portable Integer Types and Limits
C does not guarantee int, long and pointers have the same sizes on all machines. Use <stdint.h> for optional exact-width types such as int32_t, <inttypes.h> for portable format macros, and <limits.h> for properties such as INT_MAX. int32_t exists only if the implementation provides an exactly 32-bit signed integer type.
Complete C program:
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
int32_t score = 1234;
printf("Score: %" PRId32 "\n", score);
printf("INT_MAX is at least 32767: %s\n",
INT_MAX >= 32767 ? "yes" : "no");
return 0;
}
Expected output:
Score: 1234
INT_MAX is at least 32767: yes
Step-by-step explanation:
- int32_t is a signed exact-width integer on supporting implementations.
- PRId32 supplies the matching printf conversion sequence.
- Limits come from headers rather than guessed machine-specific sizes.
4.31 const, volatile and restrict โ Different Qualifiers
const prevents modification through an expression with the const-qualified type. volatile tells the compiler that accesses to certain objects must follow the languageโs observable-access rules; it does not make shared data thread-safe. restrict, introduced in C99, is a promise about how pointers access data, which can help optimisation. These qualifiers have different purposes.
Complete C program:
#include <stdio.h>
void addArrays(int n, int *restrict result,
const int *restrict left, const int *restrict right)
{
for (int i = 0; i < n; ++i)
result[i] = left[i] + right[i];
}
int main(void)
{
int a[3] = {1, 2, 3}, b[3] = {4, 5, 6}, out[3];
addArrays(3, out, a, b);
printf("%d %d %d\n", out[0], out[1], out[2]);
return 0;
}
Expected output:
5 7 9
Step-by-step explanation:
- The source arrays are read through pointers to const int.
- The restrict-qualified pointers are used with nonoverlapping arrays.
- The destination receives pairwise sums.
4.32 Quick Revision
๐ int is commonly used for integer values.
๐ float represents single-precision floating-point values.
๐ double represents double-precision floating-point values.
๐ void represents the absence of a value in certain contexts.
๐ sizeof reports size in bytes.
๐ Use sizeof() when you need the actual size on your system.
๐ Integer division discards the fractional part of the result.
4.33 Quick MCQs
Select an answer first, then click Check Answer. A correct choice becomes green. If the choice is wrong, it becomes red and the correct option is shown in green. The explanation appears below after checking.
int is the standard integer type commonly used for whole-number values.
sizeof is a C operator that reports the size in bytes of a type or object.
A character constant is written inside single quotes, such as 'A'. Double quotes create a string literal.
When both operands are integers, integer division is performed, so the fractional part is discarded and the result is 2.
double generally provides greater floating-point precision than float, although exact representation details are implementation-dependent.
4.34 ๐ฏ Programming Problems
Try each program yourself first. Use ๐ป Solve It Yourself to write and run your C code. Open a hint only when needed, and use Show Program to study the official solution after attempting the problem.
Problem 1: Declare variables of type int, float, double and char, read their values, and print them.
Input: An integer, a float, a double and a character.
Output: Print all four values with clear labels.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
int i;
float f;
double d;
char ch;
scanf("%d %f %lf %c", &i, &f, &d, &ch);
printf("int = %d\n", i);
printf("float = %.2f\n", f);
printf("double = %.3f\n", d);
printf("char = %c", ch);
return 0;
}
Problem 2: Write a program to print the size of char, int, float and double using sizeof.
Input: No input.
Output: Print the sizes in bytes on separate lines.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
printf("char = %zu\n", sizeof(char));
printf("int = %zu\n", sizeof(int));
printf("float = %zu\n", sizeof(float));
printf("double = %zu", sizeof(double));
return 0;
}
Problem 3: Write a program to calculate the average of two integers and display the result with decimal precision.
Input: Two integers.
Output: Print the average rounded to two decimal places.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
int a, b;
double average;
scanf("%d %d", &a, &b);
average = (a + b) / 2.0;
printf("Average = %.2f", average);
return 0;
}
Problem 4: Write a program demonstrating the difference between integer division and floating-point division.
Input: Two integers a and b, where b is non-zero.
Output: Print integer division and floating-point division results.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
int a, b;
scanf("%d %d", &a, &b);
printf("Integer Division = %d\n", a / b);
printf("Floating Division = %.2f", (double)a / b);
return 0;
}
Problem 5: Write a program that reads an integer and displays its value as a double.
Input: One integer.
Output: Print the converted value with two digits after the decimal point.
C Code Editor
Sample Input
Program Output
Run your program to see the output.
Test Cases
#include <stdio.h>
int main()
{
int value;
double converted;
scanf("%d", &value);
converted = value;
printf("Double = %.2f", converted);
return 0;
}
4.35 Key Takeaway
Understand three things:
1. What kind of value do I need?
2. What type is appropriate?
3. What happens when different types are used together?
These ideas become extremely important when we learn operators, expressions, arrays, pointers and functions.
๐ Program Tracing โ Data Types
Trace how integer division differs from floating-point division after an explicit type conversion.
โ
๐ค Data Types โ Interview Questions
๐ก Data Types โ Extra Tips
- Do not memorize fixed byte sizes for every machine. Except for sizeof(char) == 1, sizes of fundamental types are implementation-dependent.
- Know the correct format specifier for common types and remember that scanf uses
%lffordouble. - Be ready to explain why integer division can produce a different result from floating-point division.
- Understand when a cast such as
(double)achanges the type used by an expression. - In interviews, connect type + range/precision + operation behavior instead of memorizing only syntax.
โ๏ธ Data Types โ Extra Practice Questions
- Predict the type and result of the expression
5 + 2.5. - Explain why
5 / 2and5.0 / 2produce different results. - Write a short program that uses
sizeofwith five different types available in C. - Compare
char,int,float, anddoublewith one suitable example value for each. - Rewrite an integer-division expression so that it produces a floating-point result using an explicit cast.