Operator sizeof melaporkan berapa byte memori yang dibutuhkan sebuah tipe atau ekspresi — tanpa menjalankan ekspresi itu. Ia unik karena hasilnya sudah pasti pada saat kompilasi: compiler mengetahui ukuran semua tipe sebelum program berjalan, sehingga sizeof bisa dipakai di tempat yang menuntut konstanta, termasuk static_assert. Pada Chapter ini kita mengukur semua tipe fundamental, membuktikan bahwa operand sizeof tidak dievaluasi, dan membandingkannya dengan operator alignof yang melaporkan syarat perataan alamat. Operator ini pernah menyapa kita sekilas pada Chapter sizeof dan limits di Section Variabel dan Tipe Data; kini kita melihatnya dari sisi operator.
sizeof pada Tipe dan pada Ekspresi #
sizeof punya dua bentuk: sizeof(tipe) dengan tipe di dalam kurung, dan sizeof(ekspresi) yang melaporkan ukuran tipe hasil ekspresi tersebut. Keduanya menghasilkan bilangan bertipe std::size_t — tipe integer unsigned khusus yang dirancang untuk menyimpan ukuran dan indeks; kita akan bertemu dengannya lagi saat membahas container.
#include <iostream>
int main() {
std::cout << "Ukuran tipe fundamental (dalam byte):\n";
std::cout << "sizeof(char) = " << sizeof(char) << "\n";
std::cout << "sizeof(bool) = " << sizeof(bool) << "\n";
std::cout << "sizeof(short) = " << sizeof(short) << "\n";
std::cout << "sizeof(int) = " << sizeof(int) << "\n";
std::cout << "sizeof(long) = " << sizeof(long) << "\n";
std::cout << "sizeof(long long) = " << sizeof(long long) << "\n";
std::cout << "sizeof(float) = " << sizeof(float) << "\n";
std::cout << "sizeof(double) = " << sizeof(double) << "\n\n";
int nilai = 42;
double harga = 9.5;
std::cout << "sizeof(nilai) = " << sizeof(nilai) << "\n";
std::cout << "sizeof(harga) = " << sizeof(harga) << "\n\n";
// sizeof TIDAK mengevaluasi ekspresinya
int hitung = 0;
std::cout << "sizeof(hitung++) = " << sizeof(hitung++) << "\n";
std::cout << "hitung tetap = " << hitung << "\n\n";
// alignof: syarat perataan alamat tipe
std::cout << "alignof(int) = " << alignof(int) << "\n";
std::cout << "alignof(double) = " << alignof(double) << "\n";
// Jaminan standar: char selalu 1 byte
static_assert(sizeof(char) == 1, "char selalu 1 byte menurut standar");
return 0;
}Output yang Dihasilkan:
Ukuran tipe fundamental (dalam byte):
sizeof(char) = 1
sizeof(bool) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(long) = 8
sizeof(long long) = 8
sizeof(float) = 4
sizeof(double) = 8
sizeof(nilai) = 4
sizeof(harga) = 8
sizeof(hitung++) = 4
hitung tetap = 0
alignof(int) = 4
alignof(double) = 8Mari kita bedah:
- Baris 6-13 (
sizeof(tipe)): ukuran tipe fundamental di mesin uji (x86-64 Linux). Pola besarnya:char1,short2,int4,longdanlong long8;float4 dandouble8. - Baris 17-19 (
sizeof(nilai)dansizeof(harga)): bentuk ekspresi.nilaibertipeintsehingga dilaporkan4,hargabertipedoublesehingga8— hasilnya ditentukan tipe, bukan nilai isinya. - Baris 23-25:
sizeof(hitung++)tetap melaporkan4(ukuranint), danhitungtidak berubah — tetap0. Inilah bukti operandsizeofadalah unevaluated operand. - Baris 29-30 (
alignof):alignof(int)menghasilkan4danalignof(double)menghasilkan8, sesuai syarat perataan pada arsitektur ini. - Baris 33 (
static_assert): compiler memeriksasizeof(char) == 1pada saat kompilasi — sah karenasizeofmemang konstanta.
Operand sizeof Tidak Dievaluasi #
Perilaku paling menarik dari sizeof: compiler hanya melihat tipe operandnya, lalu membuang ekspresinya. Inilah mengapa sizeof(hitung++) tidak menaikkan hitung — kenaikan itu tidak pernah terjadi. Operand semacam ini disebut unevaluated operand, dan sifat yang sama dimiliki typeid yang akan kita temui pada Section Pemrograman Berorientasi Objek.
Konsekuensi praktisnya ada dua. Pertama, kita bisa menulis sizeof(ekspresi) dengan aman tanpa efek samping yang tidak diinginkan. Kedua, ada batasannya: operand sizeof tidak boleh memanggil fungsi yang tidak lengkap deklarasinya, dan hasilnya tidak bisa memberi tahu apa pun tentang nilai runtime. Untuk mengetahui panjang isi data saat program berjalan, gunakan ukuran yang disimpan oleh container — bukan sizeof.
Jaminan sizeof(char) == 1 #
Standar C++ menjamin tepat satu hal yang sering dianggap aksioma: sizeof(char) selalu 1, pada platform mana pun. Lebih dalam lagi, definisi “byte” di C++ adalah ukuran satu char — jadi byte di sini adalah unit storage terkecil yang bisa dialamatkan, dan lebar bitnya dilaporkan CHAR_BIT dari header <climits> (8 pada mesin umum, tetapi standar hanya menjamin minimal 8). Karena itu hasil sizeof(int) == 4 artinya int setara empat char, bukan empat byte sesuai definisi hardware tertentu.
Ukuran lain dijamin standar hanya lewat urutan relatifnya: sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long), dan sizeof(float) <= sizeof(double). Nilai eksak — misalnya int tepat 4 byte — ditentukan arsitektur dan compiler; itulah sebabnya kode yang butuh lebar pasti memakai tipe tetap seperti std::int32_t dari <cstdint> (kita pakai nanti pada Chapter Operator Overflow dan Batasan).
sizeof vs alignof: Ukuran dan Perataan #
alignof(tipe) melaporkan alignment: syarat bahwa alamat objek tipe itu harus kelipatan nilai tertentu. CPU membaca memori paling efisien pada alamat yang selaras, sehingga compiler menempatkan objek mengikuti alignof-nya. Dari output program: objek int ditempatkan di alamat kelipatan 4, objek double di kelipatan 8.
Dengan sizeof, kita kini bisa memeriksa biaya memori dari setiap pilihan tipe. Chapter berikutnya menyatukan semua operator yang sudah kita kenal menjadi satu peta aturan: precedence dan associativity — urutan mana yang compiler kerjakan lebih dulu.