C Tutorial
C Sizeof
sizeof tells you how many bytes a type or object occupies. Use it with malloc and arrays.
A count of bytes
sizeof is an operator. It asks the compiler how many bytes a type or an object uses.sizeof(int) is the size of an int. sizeof n is the size of the objectn. The result has type size_t. Print it with %zu.
The number is not always 4. An int is often four bytes, but C only promises it is large enough for the type. Write sizeof instead of hard-coding 4.
sizeof a type and sizeof an object
Parentheses are required for a type name: sizeof(int). For an object they are optional:sizeof n and sizeof(n) are the same.
Example
#include <stdio.h>
int main(void) {
int n = 0;
double x = 0.0;
printf("int: %zu\n", sizeof(int));
printf("n: %zu\n", sizeof n);
printf("double: %zu\n", sizeof(double));
printf("x: %zu\n", sizeof x);
return 0;
}sizeof n matches sizeof(int) because n is an int. Change the type of n and both lines that use n stay correct.
Array length from sizeof
For an array, sizeof nums is the whole block. sizeof nums[0] is one element. Divide them to get the count. This only works on a real array, not on a pointer.
Example
#include <stdio.h>
int main(void) {
int nums[4] = {10, 20, 30, 40};
size_t bytes = sizeof nums;
size_t count = sizeof nums / sizeof nums[0];
printf("bytes: %zu\n", bytes);
printf("count: %zu\n", count);
return 0;
}If each int is 4 bytes, bytes is 16 and count is 4. The division is the part you reuse in loops: walk count elements, not a magic 4.
A pointer is not the array
After int *p = nums;, sizeof p is the size of a pointer, not the size of the array. That is why functions that take arrays also take a length. The pointer does not carry a count.
Example
#include <stdio.h>
int main(void) {
int nums[4] = {1, 2, 3, 4};
int *p = nums;
printf("array: %zu\n", sizeof nums);
printf("pointer: %zu\n", sizeof p);
printf("element: %zu\n", sizeof *p);
return 0;
}sizeof *p is the size of one int, because *p is an int.sizeof p is the size of the address itself — often 8 on a 64-bit machine. Do not dividesizeof p by sizeof *p hoping to recover 4.
Use sizeof with malloc
Heap allocation should ask for n * sizeof(int), not n * 4. If int is wider on another machine, the expression still matches.
Example
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 3;
int *nums = malloc((size_t)n * sizeof(int));
if (nums == NULL) {
printf("malloc failed\n");
return 1;
}
nums[0] = 7;
nums[1] = 8;
nums[2] = 9;
printf("%d\n", nums[0] + nums[1] + nums[2]);
free(nums);
return 0;
}Compile these at /c/try. That is gcc, C17, and %zu forsize_t.
Next: put work in a function so you do not copy-paste the same block.
Worked examples
The short listings above are there so you can see the grammar. The programs here use the same statements on quantities that already have units: a speed, a pH, a count of bases. They are classroom numbers. Air resistance is ignored. g is 9.81 m/s² unless a line says otherwise.
Open them in the C editor at /c/try. Change one measurement and check whether the result still has the right unit.
Physics
How large a sample record is
A magnetic field in tesla is a double. A repeat count is an int. Together they are a struct. malloc needs the size in bytes, not a guess. On a typical desktop the struct is 16 bytes because of alignment, not 8 + 4 = 12.
sizeof is evaluated by the compiler. It does not measure the magnet.
Example
#include <stdio.h>
int main(void) {
struct Sample {
double tesla;
int n;
};
printf("double %zu bytes\n", sizeof(double));
printf("struct %zu bytes\n", sizeof(struct Sample));
return 0;
}Maths
Room for 100 coordinates
A list of 100 doubles is 100 × sizeof(double). If double is 8 bytes, that is 800 bytes. That product is what you pass to malloc, not 100, and not 100 * 4 from a 32-bit habit.
Example
#include <stdio.h>
int main(void) {
printf("%zu bytes for 100 doubles\n", 100 * sizeof(double));
return 0;
}