Karena ukuran tipe dasar di C bergantung pada compiler dan platform, kita membutuhkan cara untuk memeriksa ukuran secara programatik. Inilah peran operator sizeof dan tipe size_t. Operator sizeof dievaluasi pada saat kompilasi (dengan pengecualian array variabel length) dan menghasilkan jumlah byte yang dipakai oleh tipe atau variabel. Tipe size_t adalah tipe unsigned yang dijamin cukup besar untuk menampung ukuran objek apa pun yang bisa dialokasikan di platform. Pada Chapter ini kita akan memakai keduanya untuk menulis kode yang portabel antar sistem operasi dan arsitektur.
Cara Kerja Operator sizeof #
Operator sizeof menerima satu operand berupa tipe (di dalam kurung) atau ekspresi variabel. Hasilnya bertipe size_t. Standar C menjamin sizeof(char) == 1 di semua platform; tipe lain bergantung pada ABI. Operator ini dievaluasi pada saat kompilasi, sehingga tidak ada biaya runtime. Pengecualian adalah variable-length array (VLA) yang ukurannya baru diketahui saat runtime.
#include <stdio.h>
int main(void) {
int i = 0;
double d = 0.0;
printf("Ukuran int = %zu byte\n", sizeof(int));
printf("Ukuran double = %zu byte\n", sizeof(double));
printf("Ukuran char = %zu byte\n", sizeof(char));
printf("Ukuran i = %zu byte\n", sizeof(i));
printf("Ukuran (i + d) = %zu byte\n", sizeof(i + d));
return 0;
}Output yang Dihasilkan:
Ukuran int = 4 byte
Ukuran double = 8 byte
Ukuran char = 1 byte
Ukuran i = 4 byte
Ukuran (i + d) = 8 byteMari kita telaah baris-baris kode di atas:
- Baris 6 (
sizeof(int)): tipe harus diletakkan dalam kurung; hasilnya4di platform x86_64 GCC. - Baris 7 (
sizeof(double)): hasilnya8byte untuk presisi ganda IEEE 754. - Baris 8 (
sizeof(char)): dijamin1oleh standar C; menjadi patokan unitsizeof. - Baris 9 (
sizeof(i)): jika operand adalah variabel, kurung boleh dihilangkan; hasilnya sama dengansizeof(int)karenaibertipeint. - Baris 10 (
sizeof(i + d)): ekspresii + ddievaluasi tipe-nya (bukan nilainya). Karenadbertipedouble,idipromosikan kedouble, sehingga hasil ekspresi bertipedouble;sizeofmenghasilkan8.
Menghitung Jumlah Elemen Array #
Salah satu penggunaan sizeof paling umum adalah menghitung jumlah elemen array statis dengan rumus sizeof(arr) / sizeof(arr[0]). Pembagian ukuran total array dengan ukuran satu elemen menghasilkan jumlah elemen. Pola ini portabel dan tidak bergantung pada tipe elemen.
#include <stdio.h>
int main(void) {
size_t ukuran_arr = 0;
int arr[5] = {1, 2, 3, 4, 5};
/* sizeof array = jumlah_elemen * ukuran_elemen */
ukuran_arr = sizeof(arr);
printf("sizeof(arr) = %zu byte\n", ukuran_arr);
printf("sizeof(arr[0]) = %zu byte\n", sizeof(arr[0]));
printf("jumlah elemen = %zu\n", sizeof(arr) / sizeof(arr[0]));
return 0;
}Output yang Dihasilkan:
sizeof(arr) = 20 byte
sizeof(arr[0]) = 4 byte
jumlah elemen = 5Pada baris 8, sizeof(arr) menghasilkan 20 karena 5 elemen int masing-masing 4 byte. Pada baris 9, sizeof(arr[0]) menghasilkan 4—ukuran satu elemen. Pada baris 10, pembagian 20 / 4 menghasilkan 5, yaitu jumlah elemen.
Tipe size_t untuk Menyimpan Ukuran #
Tipe size_t didefinisikan pada header <stddef.h> (dan disertakan secara tidak langsung oleh banyak header standar seperti <stdio.h>). Tipe ini unsigned dan ukurannya dipilih agar bisa menampung ukuran objek maksimum yang bisa dialokasikan di platform. Pada x86_64, size_t 8 byte (64-bit). Pada sistem 32-bit, size_t 4 byte.
#include <stdio.h>
#include <stdint.h>
int main(void) {
size_t a = 100;
size_t b = 50;
printf("a = %zu\n", a);
printf("b = %zu\n", b);
printf("a + b = %zu\n", a + b);
printf("a - b = %zu\n", a - b);
printf("Ukuran size_t = %zu byte\n", sizeof(size_t));
printf("SIZE_MAX = %zu\n", (size_t)-1);
return 0;
}Output yang Dihasilkan:
a = 100
b = 50
a + b = 150
a - b = 50
Ukuran size_t = 8 byte
SIZE_MAX = 18446744073709551615Pada baris 13, sizeof(size_t) menghasilkan 8 di x86_64, sesuai dengan lebar address space 64-bit. Pada baris 14, cast (size_t)-1 memanfaatkan wrap-around unsigned: nilai -1 diubah menjadi bilangan positif terbesar yang bisa ditampung size_t, yaitu 2^64 - 1 = 18.446.744.073.709.551.615. Nilai ini sama dengan konstanta SIZE_MAX dari <stdint.h>.
Format Specifier %zu #
Karena size_t bisa berukuran 32 atau 64 bit, kita tidak bisa memakai %d atau %u secara konsisten. Standar C99 menambahkan format specifier %zu khusus untuk size_t. Specifier ini otomatis menyesuaikan ukuran tipe dengan platform. Sebelum C99, programmer terpaksa melakukan cast eksplisit ke unsigned long dan memakai %lu, tetapi cara ini bisa menimbulkan masalah pada platform 64-bit.
Dengan sizeof dan size_t, kita siap menulis kode yang adaptif terhadap perbedaan platform. Selanjutnya, kita akan memetakan seluruh batas nilai tipe integer melalui konstanta yang disediakan header limits.h.