C Data Types
Choose a representation, inspect sizes with sizeof, and convert values without pretending sizes are universal.
A type is a representation, not a label
A C type decides which values an object can hold, which operators apply, and how those values are stored on this implementation. It is not a Python-style runtime tag you can query after the fact. Choose the type that matches the problem: a count, a character code, a measurement, or a yes/no flag.
Later lessons add arrays, pointers, and structures. This lesson introduces the scalar types you will use constantly. Detailed collection behavior belongs in C Arrays and C Strings.
Integer types have minimum ranges, not universal sizes
The usual whole-number type is int. short and long exist when you need a smaller or larger integer, and signed versus unsigned changes whether negative values are representable. The C standard requires minimum ranges—for example int must cover at least −32767 through 32767—but it does not require int to be 32 bits on every machine.
Do not write production code that assumes int is four bytes because that happened to be true on one laptop. When a width is a requirement, use a fixed-width type from <stdint.h> such as int32_t, or document the limit you actually need.
A character code and a small integer
Large enough for a character. Signedness of plain char is implementation-defined.
The default whole-number type
Use it for counts and indexes unless you have a documented width requirement.
At least as wide as int
Useful when a quantity can exceed a 16-bit minimum int. Still not a universal 64-bit promise for long.
Non-negative integers
Wraps modulo 2n on overflow. Do not mix signed and unsigned comparisons casually.
char is an integer type
A character literal such as 'A' has an integer value—the character's code. Printing with %c shows the glyph; printing with %d shows the code. That is why C has no built-in string object: text is an array of char values ending in \0, taught in C Strings.
#include <stdio.h>
int main(void) {
char grade = 'A';
printf("Grade letter: %c\n", grade);
printf("Grade code: %d\n", grade);
return 0;
}Compile this locally. The lesson runner used in earlier pages understands int, double, and character arrays, not a standalone char object. The language rule is the same: char is an integer type.
float and double approximate real numbers
float and double store binary floating-point values. They are appropriate for measurements and rates, not for money that must be exact to a decimal cent. double is the usual beginner choice for fractional quantities. Binary floating-point cannot represent every decimal fraction exactly, so later numeric work needs a deliberate rounding or decimal policy.
sizeof reports this implementation
sizeof(int) is the size in bytes of an int on the compiler and target you are using. It is a useful measurement, not a portable constant you should hard-code into a protocol. Compile the snippet locally and compare it with a friend’s machine before treating a size as a file format.
#include <stdio.h>
int main(void) {
printf("char: %zu\n", sizeof(char));
printf("int: %zu\n", sizeof(int));
printf("double: %zu\n", sizeof(double));
return 0;
}sizeof(char) is 1 by definition. The others are implementation-defined. Use %zu for a size_t value such as the result of sizeof.
Convert on purpose
C converts operands in mixed expressions using integer promotions and the usual arithmetic conversions. A common surprise is integer division: 7 / 2 is 3 because both operands are int. Writing 7 / 2.0 makes one operand floating-point, so the result can keep a fraction. An explicit cast such as (double)total / count documents the conversion. Casts do not make overflow safe; they only reinterpret or convert a value according to the language rules.
Compare integer and floating-point division
Predict both printed results before running. Then change 7 to 8 and explain which line changes.
Edit the program, predict its output, then run it.
bool is a small integer; C has no None
C11 and later provide bool through <stdbool.h>, with true and false. Historically, C treated zero as false and nonzero as true—the rule C If Else still depends on. There is no Python None. Absence is modeled with a sentinel, a flag, or a null pointer once you reach pointers.
Inspect types on your compiler
Save the sizeof program as types.c and compile with warnings enabled. The printed sizes are facts about that build, not about every C implementation.
clang -std=c11 -Wall -Wextra -Wpedantic -Wconversion types.c -o types./typesgcc -std=c11 -Wall -Wextra -Wpedantic -Wconversion types.c -o types./typescl /W4 /std:c11 types.ctypes.exeIndependent lab: report mixed types
Write a small program that prints an int count, a double duration, and a char grade. Predict the printf placeholders before you run it. Then add a sizeof line for int and explain why that number might differ on another computer.
Lesson review
- A type decides representation and operations, not a runtime object tag.
int,char,float, anddoublehave standard minimums; exact widths are implementation-defined unless you use a fixed-width type.sizeofmeasures this compiler and target.- Integer division discards a fraction; convert deliberately when the fraction matters.
- C strings are character arrays, taught next in the strings lesson.