Saya bertanya-tanya mengapa kode semacam ini bisa mendapatkan ukuran array tes? Saya tidak terbiasa dengan tata bahasa di template. Mungkin seseorang bisa menjelaskan arti kode di bawah template<typename,size_t>
. Selain itu, tautan referensi juga disukai.
#define dimof(array) (sizeof(DimofSizeHelper(array)))
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
void InitDynCalls()
{
char test[20];
size_t n = dimof(test);
printf("%d", n);
}
c++
visual-c++
Iblis bayangan
sumber
sumber
std::array
ataustd::vector
....Jawaban:
Ini sebenarnya sangat sulit untuk dijelaskan, tapi saya akan mencobanya ...
Pertama,
dimof
memberi tahu Anda dimensi , atau jumlah elemen dalam array. (Saya percaya "dimensi" adalah terminologi yang lebih disukai di lingkungan pemrograman Windows).Ini perlu karena
C++
danC
tidak memberi Anda cara asli untuk menentukan ukuran array.Seringkali orang beranggapan
sizeof(myArray)
akan bekerja, tetapi itu sebenarnya akan memberi Anda ukuran dalam memori, bukan jumlah elemen. Setiap elemen mungkin membutuhkan lebih dari 1 byte memori!Selanjutnya, mereka mungkin mencoba
sizeof(myArray) / sizeof(myArray[0])
. Ini akan memberikan ukuran dalam memori array, dibagi dengan ukuran elemen pertama. Tidak apa-apa, dan banyak digunakan dalamC
kode. Masalah utama dengan ini adalah bahwa hal itu akan berfungsi jika Anda melewatkan pointer bukan array. Ukuran pointer di memori biasanya akan 4 atau 8 byte, meskipun hal itu menunjuk mungkin menjadi array elemen 1000s.Jadi hal berikutnya yang harus dicoba
C++
adalah menggunakan templat untuk memaksa sesuatu yang hanya berfungsi untuk array, dan akan memberikan kesalahan kompilator pada pointer. Ini terlihat seperti ini:Template hanya akan berfungsi dengan array. Ini akan menyimpulkan jenis (tidak benar-benar diperlukan, tetapi harus ada di sana untuk mendapatkan template untuk bekerja) dan ukuran array, lalu mengembalikan ukurannya. Cara templat ini ditulis tidak dapat bekerja dengan pointer.
Biasanya Anda bisa berhenti di sini, dan ini ada di C ++ Standard Libary as
std::size
.Peringatan: di bawah sini ia masuk ke wilayah pengacara bahasa berbulu.
Ini cukup keren, tetapi masih gagal dalam kasus tepi yang tidak jelas:
Perhatikan bahwa array
x
yang dideklarasikan , tetapi tidak didefinisikan . Untuk memanggil suatu fungsi (yaituArraySize
) dengannya,x
harus ditentukan .Anda tidak dapat menautkan ini.
Kode yang Anda miliki dalam pertanyaan adalah cara mengatasinya. Alih-alih benar-benar memanggil fungsi, kami mendeklarasikan fungsi yang mengembalikan objek dengan ukuran yang tepat . Lalu kami menggunakan
sizeof
trik itu.Ini terlihat seperti kita memanggil fungsi, tetapi
sizeof
murni kompilasi waktu konstruksi, sehingga fungsi pernah benar-benar dipanggil.Catatan Anda sebenarnya tidak bisa mengembalikan array dari suatu fungsi, tetapi Anda bisa mengembalikan referensi ke array.
Kemudian
DimofSizeHelper(myArray)
adalah ekspresi yang tipe array padaN
char
s. Ekspresi sebenarnya tidak harus dapat dijalankan, tetapi masuk akal pada waktu kompilasi.Karena itu
sizeof(DimofSizeHelper(myArray))
akan memberi tahu Anda ukuran pada waktu kompilasi apa yang akan Anda dapatkan jika Anda benar-benar memanggil fungsi tersebut. Meskipun sebenarnya kita tidak menyebutnya.Jangan khawatir jika blok terakhir itu tidak masuk akal. Ini adalah trik aneh untuk mengatasi kasus tepi yang aneh. Inilah sebabnya mengapa Anda tidak menulis kode semacam ini sendiri, dan biarkan pelaksana perpustakaan khawatir tentang omong kosong semacam ini.
sumber
DimofSizeHelper
adalah fungsi templat yang mengambilT(&)[N]
parameter - alias referensi ke C-array elemen N jenisT
dan mengembalikanchar (&)[N]
alias referensi ke array N karakter. Dalam C ++ char adalah byte dalam penyamaran dansizeof(char)
dijamin1
oleh standar.n
ditugaskan ukuran tipe pengembalianDimofSizeHelper
,sizeof(char[N])
yang merupakanN
.Ini agak berbelit-belit
dan tidak perlu. Cara yang biasa dilakukan adalah:Karena C ++ 17 ini juga tidak perlu, seperti yang kita
std::size
lakukan ini, tetapi dengan cara yang lebih umum, bisa mendapatkan ukuran wadah gaya stl.Seperti yang ditunjukkan oleh BoBTFish, perlu untuk kasus tepi.
sumber
std::extent
sejak C ++ 11 yang merupakan waktu kompilasi.