Cara memeriksa apakah bilangan bulat lebar tetap didefinisikan

25

Dalam C ++, integer lebar tetap didefinisikan sebagai opsional , tetapi saya tidak bisa menemukan cara yang disarankan untuk memeriksa apakah mereka benar-benar didefinisikan.

Apa yang akan menjadi cara portabel untuk memeriksa apakah integer lebar tetap tersedia?

Rick de Water
sumber
Sepertinya tidak ada fitur uji makro , tapi saya kira Anda bisa melakukannya#if defined(INT8_MIN)
Zereges
2
Jika pustaka std tidak menyediakan makro uji fitur untuk itu, maka Anda dapat memeriksa apakah rantai alat yang Anda gunakan menyediakannya untuk itu atau memungkinkan Anda untuk menentukan tes sendiri. CMake, misalnya, memungkinkan Anda untuk menguji fitur bahasa tertentu dengan mengkompilasi cppfile yang ditentukan dan tergantung pada apakah kompilasi gagal atau tidak makro yang dapat Anda tentukan diatur.
t.niese
Jika Anda lebih suka autoconf daripada cmake, ia memiliki tes yang sudah ditentukan sebelumnya. AC_TYPE_INT8_Tdll.
Shawn
Jika ada yang memiliki skor tag di stdint , IMO cstdint harus dinominasikan sebagai sinonim ( stackoverflow.com/tags/stdint/synonim ). Saya tidak berpikir kita perlu tag C dan C ++ terpisah untuk hal yang tidak jelas ini; tag utama pada pertanyaan sudah cukup.
Peter Cordes
1
@PeterCordes Berhasil kali ini: stackoverflow.com/tags/stdint/synonim
Andrew Henle

Jawaban:

16

Untuk menentukan apakah tipe integer lebar tetap disediakan, Anda dapat memeriksa apakah salah satu dari yang sesuai [U]INT*_MAXatau [U]INT*_MINmakro didefinisikan.

// may be necessary for your C++ implementation
#define __STDC_LIMIT_MACROS 
#include <cstdint>

#ifdef INT32_MAX
// int32_t must be available to get here
int32_t some32bitIntVariable;
#endif

Per 7.20 Jenis integer<stdint.h> , paragraf 4 dari standar C11 (perhatikan bagian yang dicetak tebal):

Untuk setiap jenis yang dijelaskan di sini yang disediakan oleh implementasi, <stdint.h>harus menyatakan typedefnama itu dan mendefinisikan makro terkait . Sebaliknya, untuk setiap jenis yang dijelaskan di sini bahwa implementasi tidak menyediakan, <stdint.h>tidak boleh menyatakan typedefnama itu atau mendefinisikan makro terkait .

C ++ mewarisi implementasi C melalui <cstdint>. Lihat <cstdint>vs<stdint.h> untuk beberapa detail. Juga lihat Apa artinya __STDC_LIMIT_MACROSdan __STDC_CONSTANT_MACROSartinya? untuk detail tentang __STDC_LIMIT_MACROS.

Dengan demikian, jika int32_ttersedia, INT32_MAXdan INT32_MINharus #define'd. Sebaliknya, jika int32_ttidak tersedia, keduanya INT32_MAXtidak INT32_MINdiizinkan untuk menjadi #define'd.

Catat juga, seperti yang dikatakan @NicolBolas dalam jawaban lain , mungkin tidak perlu benar-benar memeriksa.

Andrew Henle
sumber
Ini akan lebih pendek untuk memeriksa [U]INT*_Cbukannya makro min & max
phuclv
1
@ phuclv Kecuali itu bukan hal yang sama. misalnya INT64_Cdidefinisikan jika int64_least_ttersedia, bukan jika int64_ttersedia. Lihat dokumentasi
Lightness Races di Orbit
19

Secara garis besar ... Anda tidak.

Jika Anda perlu menggunakan tipe integer berukuran tetap, maka itu berarti Anda secara eksplisit membutuhkan tipe integer tersebut dari ukuran spesifiknya. Artinya, kode Anda tidak akan berfungsi jika Anda tidak bisa mendapatkan bilangan bulat dari ukuran itu. Jadi Anda harus menggunakannya; jika seseorang menggunakan kode Anda pada kompiler yang tidak memiliki tipe kata, maka kode Anda tidak akan dikompilasi. Tidak masalah, karena kode Anda tidak akan berfungsi jika dikompilasi.

Jika Anda tidak benar-benar membutuhkan bilangan bulat berukuran tetap tetapi hanya menginginkannya karena alasan lain, maka gunakan int_least_*tipenya. Jika implementasinya dapat memberi Anda ukuran yang tepat, maka least_*jenisnya akan memiliki ukuran itu.

Nicol Bolas
sumber
4
Ini tidak benar. Saya telah menulis rintisan passthroughs yang mengimplementasikan operator = / etc untuk platform yang tidak mendukung uint8_t sebelumnya. Tetapi untuk tujuan efisiensi dan debugging Anda tidak ingin menggunakan passthrough kecuali yang sebenarnya diperlukan.
TLW
@ TTW: " Saya sudah menulis rintisan passthroughs yang mengimplementasikan operator = / etc untuk platform yang tidak mendukung uint8_t sebelumnya. " OK, tapi ... kenapa? Kode apa yang Anda tulis yang perlu memastikan bahwa byte adalah 8 bit (yang mungkin mengapa Anda gunakan uint8_t), tetapi kode ini entah bagaimana harus dijalankan pada platform di mana byte bukan 8 bit (yang, selain menggunakan implementasi C ++ lama, akan menjadi satu-satunya alasan mengapa uint8_ttidak tersedia)? Artinya, di luar kompatibilitas ke belakang, mengapa Anda perlu melakukan ini?
Nicol Bolas
milik jadi tidak bisa mengatakan terlalu banyak. Basis kode bersama yang diperlukan untuk mendukung, antara lain, tumpukan perangkat keras yang agak unik. uint8_tadalah jauh lebih jelas daripada pendekatan sebelum ad-hoc (dan sering rusak).
TLW
Jika Anda memiliki algoritme yang dinyatakan dalam misalnya byte 8-bit, passthrough adalah sesuatu yang dapat Anda tulis sekali dan mudah untuk diuji. Sedangkan memperbaiki setiap tempat adalah ad-hoc dan mudah salah secara halus. O(1)versus O(n)usaha. Alasan yang sama mengapa orang menggunakan mis uint16_t. Anda bertanya "mengapa tidak menggunakan uint32_t dan melemparkannya sendiri?", Yang jawabannya harus jelas.
TLW
@ TTW: " Alasan yang sama mengapa orang menggunakan mis. Uint16_t. " Itu bukan alasan saya untuk menggunakan uint16_t. Alasan saya adalah bahwa saya berkomunikasi dengan perangkat / format / etc yang mengharapkan untuk mendapatkan tepat 16 bit data yang diformat sebagai biner, integer unsigned menggunakan endian untuk mesin saya, dan jika saya tidak bisa mendapatkan tipe yang tepatnya itu, maka berkomunikasi secara efektif dengannya jauh lebih sulit. Program saya (dan API yang saya gunakan dengannya) pada dasarnya tidak dapat berfungsi pada mesin yang tidak menyediakannya.
Nicol Bolas