Berikut adalah kode yang dikompilasi di dev c ++ windows:
#include <stdio.h>
int main() {
int x = 5;
printf("%d and ", sizeof(x++)); // note 1
printf("%d\n", x); // note 2
return 0;
}
Saya berharap x
menjadi 6 setelah mengeksekusi catatan 1 . Namun, hasilnya adalah:
4 and 5
Adakah yang bisa menjelaskan mengapa x
tidak naik setelah catatan 1 ?
VLAs
yang tidak ada yang lain lakukan.Jawaban:
Dari Standar C99 (penekanannya adalah milik saya)
sumber
N
dari stdin dan membuatint array[N]
. Ini adalah salah satu fitur C99, tidak tersedia di C ++.sizeof(int[++x])
(benar-benar ide yang buruk, bagaimanapun)++
dapat dievaluasi.gcc
,clang
dan di ideone.com/Pf7iFsizeof
adalah operator waktu kompilasi , jadi pada saat kompilasisizeof
dan operasinya digantikan oleh nilai hasil. The operan tidak dievaluasi (kecuali bila itu adalah panjang variabel array) sama sekali; hanya jenis hasilnya yang penting.Keluaran:
sebagai
short
menempati 2 byte pada mesin saya.Mengubah jenis fungsi yang dikembalikan ke
double
:akan memberikan
8
sebagai output.sumber
sizeof(foo)
berusaha sangat keras untuk menemukan ukuran ekspresi pada waktu kompilasi:6.5.3.4:
Singkatnya: array panjang variabel, jalankan saat runtime. (Catatan: Array Panjang Variabel adalah fitur khusus - bukan array yang dialokasikan dengan
malloc(3)
.) Jika tidak, hanya jenis ekspresi yang dihitung, dan pada waktu kompilasi.sumber
sizeof
adalah operator built-time kompilasi dan bukan fungsi. Ini menjadi sangat jelas dalam kasus Anda dapat menggunakannya tanpa tanda kurung:sumber
sizeof
operator adalah bukan operator saat kompilasi, Anda hanya perlu memberikan VLA untuk memikirkan hal ini.Catatan
Jawaban ini digabungkan dari duplikat, yang menjelaskan tanggal terakhir.
Asli
Kecuali untuk array panjang variabel, sizeof tidak mengevaluasi argumennya. Kita bisa melihat ini dari draft bagian standar C99
6.5.3.4
Ukuran operator paragraf 2 yang mengatakan:Sebuah komentar ( sekarang dihapus ) bertanya apakah sesuatu seperti ini akan dievaluasi saat berjalan:
dan memang itu akan terjadi, sesuatu seperti ini juga akan berhasil ( Lihat mereka berdua hidup ):
karena keduanya adalah array panjang variabel. Meskipun, saya tidak melihat banyak kegunaan praktis di salah satu.
Catatan, array panjang variabel dicakup dalam rancangan bagian standar C99 Deklarator
6.7.5.2
array paragraf 4 :Memperbarui
Di C11 jawaban berubah untuk kasus VLA, dalam kasus-kasus tertentu tidak ditentukan apakah ekspresi ukuran dievaluasi atau tidak. Dari bagian
6.7.6.2
deklarasi Array yang berbunyi:Misalnya dalam kasus seperti ini ( lihat langsung ):
sumber
sizeof
secara efektif adalah makro - ia tidak membuat kode, tetapi mendahului nilai yang diharapkan dan menyimpannya langsung ke dalam kode. Perhatikan bahwa ini adalah satu - satunya perilaku sampai C99, karena VBA tidak ada (saya tidak pernah benar-benar mendengarnya sampai jawaban ini, percaya atau tidak!)sizeof (char[x++]);
menggunakan nilaix
untuk apa pun selain menentukan nilai ekspresix++
dan nilai baru untukx
, yang keduanya normal dengan operator itu?char[x++]
adalah VLA. kelihatannya sepertichar*
mata saya yang tidak kenal.Karena operan
sizeof
operator tidak dievaluasi, Anda dapat melakukan ini:Demo online: http://ideone.com/S8e2Y
Artinya, Anda tidak perlu mendefinisikan fungsi
f
jika hanya digunakansizeof
. Teknik ini banyak digunakan dalam metaprogramming template C ++, karena bahkan dalam C ++, operansizeof
tidak dievaluasi.Mengapa ini bekerja? Ini bekerja karena
sizeof
operator tidak beroperasi pada nilai , melainkan beroperasi pada jenis ekspresi. Jadi ketika Anda menulissizeof(f())
, ini beroperasi pada tipe ekspresif()
, dan yang tidak lain adalah tipe kembalinya fungsif
. Jenis kembali selalu sama, tidak peduli berapa nilai fungsi akan kembali jika itu benar-benar dijalankan.Di C ++, Anda dapat meratakan ini:
Namun sepertinya, dalam
sizeof
, saya pertama kali membuat contohA
, dengan menulisA()
, dan kemudian memanggil fungsif
pada contoh, dengan menulisA().f()
, tetapi tidak ada hal seperti itu terjadi.Demo: http://ideone.com/egPMi
Berikut adalah topik lain yang menjelaskan beberapa sifat menarik lainnya dari
sizeof
:sumber
Eksekusi tidak dapat terjadi selama kompilasi. Jadi
++i
/i++
tidak akan terjadi. Jugasizeof(foo())
tidak akan menjalankan fungsi tetapi mengembalikan tipe yang benar.sumber
sizeof
konstanta waktu kompilasi"?sizeof
berjalan pada waktu kompilasi, tetapix++
hanya dapat dievaluasi pada saat dijalankan. Untuk mengatasi ini, standar C ++ menentukan bahwa operansizeof
tidak dievaluasi. Standar C mengatakan:sumber
sizeof()
operator memberikan ukuran tipe data saja, tidak mengevaluasi elemen dalam.sumber
sizeof()
operator bertindak secara rekursif, dan akan mendapatkan ukuran dalam byte dari semua elemen wadah, anggota kelas atau struktur, dll. Anda dapat membuktikan ini sendiri dengan sangat mudah dengan membuat kelas sederhana dengan beberapa anggota dan memanggilnyasizeof()
. (Namun, apa pun di sana yang merupakan pointer tidak dapat melihat ukuran - hanya ukuran pointer.) Ini terjadi semua pada waktu kompilasi, seperti komentator lain menyatakan: ekspresi di dalamsizeof()
tidak dievaluasi.