C ++ standardı int türünün uzunluğunu belirtir?


696

Temel C ++ türlerinin boyutu hakkında ayrıntılı bilgi arıyorum. Mimariye (16 bit, 32 bit, 64 bit) ve derleyiciye bağlı olduğunu biliyorum.

Ancak C ++ için herhangi bir standart var mı?

32-bit bir mimaride Visual Studio 2008 kullanıyorum. İşte ne olsun:

char  : 1 byte
short : 2 bytes
int   : 4 bytes
long  : 4 bytes
float : 4 bytes
double: 8 bytes

Ben boyutlarını belirten güvenilir bilgi daha pek başarılı olmayan, bulmaya çalıştık char, short, int, long, double, floatfarklı mimari ve derleyici altında (ve diğer türleri aklıma gelmedi).


18
@thyrgle onun seçim değil ... esnek olması gerektiğini destekleyecek çok mimariler var.
Krakkos


4
Neden tüm belirsiz türleri kaldırmıyorlar ve bunları belirli bit uzunluğu türlerine göre standartlaştırmıyorlar, örneğin int32_t, uint32_t, int64_t vb.
developerbmw

5
@thyrgle Böyle bir şeyi standartlaştırmak aslında oldukça zor. JVM'nin çalışma şekli nedeniyle bu şeylerin sabit olduğu Java'dan farklı olarak, C / C ++, herhangi bir fantezi-pancy soyutlama katmanı olmadan (en azından Java kadar değil) çalıştırıldıkları sisteme bağlı kalmak zorundadır. arasında. İnt büyüklüğü önemli bir kullanabilmesi ise int16_t, int32_tve int64_t(gerek iostreamyanlış hatırlamıyorsam bunun için ekleyin). Bu konuda güzel olan şey, int64_t'ın 32 bit sistemde sorun yaşamaması gerektiğidir (bu, performansı etkileyecektir).
rbaleksandar

5
@rbaleksandar Aslında tanımlanmışlar <cstdint>, değil <iostream>.
Justin Time - Monica'yı

Yanıtlar:


685

C ++ standardı bayt cinsinden integral türlerin boyutunu belirtmez, ancak tutabilmeleri gereken minimum aralıkları belirtir. Gerekli aralıktan bit cinsinden minimum boyutu çıkarabilirsiniz. Bundan bayt cinsinden minimum boyutu ve bayttaki bit sayısını tanımlayanCHAR_BIT makronun değerini çıkarabilirsiniz . En belirsiz platformlar hariç 8'dir ve 8'den az olamaz. Bunun nedeni, "Unicode UTF-8 kodlama formunun sekiz bitlik kod birimlerini" tutacak kadar büyük olması gerektiğidir.

Bunun için ek bir kısıtlama char, boyutunun her zaman 1 bayt veya CHAR_BITbit (dolayısıyla ad) olmasıdır. Bu standartta açıkça belirtilmiştir.

C standardı, C ++ standardı için normatif bir referanstır , bu nedenle bu gereksinimleri açıkça belirtmese de, C ++ , C standardının (sayfa 22) gerektirdiği ve Veri Türü Aralıklarındakilerle aynı olan minimum aralıkları gerektirir . MSDN :

  1. signed char: -127 ila 127 (not, -128 ila 127 değil; 1'in tamamlayıcı ve işaret ve büyüklük platformlarını barındırır)
  2. unsigned char: 0 ila 255
  3. "düz" char: signed charveya ile aynı unsigned char, uygulama tanımlı
  4. signed short: -32767 - 32767
  5. unsigned short: 0 ile 65535 arasında
  6. signed int: -32767 - 32767
  7. unsigned int: 0 ile 65535 arasında
  8. signed long: -2147483647 ila 2147483647
  9. unsigned long: 0 ile 4294967295
  10. signed long long: -9223372036854775807 ila 9223372036854775807
  11. unsigned long long: 0 ile 18446744073709551615

Bir C ++ (veya C) uygulaması, bayt cinsinden bir türün boyutunu sizeof(type)herhangi bir değere kadar tanımlayabilir

  1. ifade sizeof(type) * CHAR_BIT, gerekli aralıkları içerecek kadar yüksek sayıda bit olarak değerlendirilir ve
  2. türün sırası hala geçerlidir (örn. sizeof(int) <= sizeof(long)).

Tüm bunları bir araya getirerek şunları garanti ediyoruz:

  • char,, signed charve unsigned charen az 8 bit
  • signed short, unsigned short, signed intVe unsigned inten az 16 bit
  • signed longve unsigned longen az 32 bit
  • signed long longve unsigned long longen az 64 bit

En az kadar hassaslık sağlayan boyutun dışında floatveya doubledışında hiçbir garanti verilmez .doublefloat

Gerçek uygulama spesifik aralıklar bulunabilir <limits.h>C başlık veya <climits>C ++ (ya da daha iyi, şablon std::numeric_limitsolarak <limits>başlığın).

Örneğin, aşağıdakiler için maksimum aralığı şu şekilde bulabilirsiniz int:

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++ :

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();

49
Daha ziyade, C ++ standardı, "1 " anlamına gelen byte kelimesini kullanır charve olağan anlamı kullanmaz.
Ben Voigt

4
@Programmer Cevabı (parantez içinde 1. nokta notu) veya gerçek standardın (cevaba bağlı olarak) ifadesini okuyun. C standardı, en yaygın 2'nin tamamlayıcısından farklı temsili olan 1'in tamamlayıcı mimarilerini barındırır. Minimum garantili aralıklar, neredeyse her zaman bir uygulamanın sağladığı gerçek aralıklardan farklı olacaktır.
Alex B

9
@Alex B, cevabınızda double hakkında hiçbir şeyden bahsetmediniz. Kayan noktalı değişkenler için cevabınızı güncelleyebilir misiniz?
Cool_Coder

3
@Cool_Coder: Kayan nokta, mesajların boyutunu kolayca iki katına çıkaran ek bir balık su ısıtıcısıdır.
Deduplicator

3
@Mooing Duck: "tüm C ++ sürümleri [imzalı karakter türleri için] 256 farklı değer gerektiriyordu" Hayır, bu daha yeni C ++ özelliklerinde düzeltilene kadar doğru değildi. Daha eski özellikler, imzalı karakter türlerinin bir sayıya eşlenmeyen bit kalıplarına sahip olmasına izin verdi, bu nedenle 256 farklı değer olması gerekliliği yoktu. "İmzasız karakter türleri için değer gösteriminin tüm olası bit kalıpları sayıları temsil eder. Bu gereksinimler diğer türler için geçerli değildir."
Adrian McCarthy

241

32 bit sistemler için 'de facto' standardı ILP32'dir - yani int, longve işaretçi 32 bitlik miktarlardır.

64 bit sistemler için, birincil Unix 'de facto' standardı LP64'tür longve işaretçi 64 bittir (ancak int32 bittir). - Windows 64 bit standart LLP64 olduğunu long longve işaretçi 64-bit (ama longve inthem 32 bit vardır).

Bir kerede, bazı Unix sistemleri bir ILP64 kuruluşu kullandı.

Bu fiili standartların hiçbiri C standardı (ISO / IEC 9899: 1999) tarafından düzenlenmemiştir, ancak hepsine izin verilir.

Ve, tanımı gereği, sizeof(char)bir 1Perl yapılandırmak komut testinde rağmen.

Makine (Crays) vardı Not olduğu CHAR_BITanlamına O ile 8, IIRC çok daha büyük, sizeof(int)aynı zamanda 1 olduğu, çünkü her ikisi de charve inttakip edilen 32 bit.


73
Teoride şeylerin nasıl olduğu yerine, en önemli durumlarda olayların gerçekte nasıl olduğunu belirtmek için +1. 32bit kullanmak isterseniz int, 64bit kullanmak istiyorsanız uzun. Yerel kullanmak istiyorsanız size_t kullanın. Değiştiği için "düz" olmaktan kaçının. Çoğu uygulama için bu işe yarar.
Eloff

37
Cevap için +1. @Eloff: aksine ... 32 bitlik kullanım [u]int32_tveya benzeri istiyorsanız, 64 bitlik kullanım [u]int64_tistiyorsanız ... bunlar için bir başlığınız yoksa, tercihen derleme zamanı seçimiyle boyutu doğrulamak için bu tür veya statik iddialar. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Kesin boyutlar o kadar önemli değilse ve yalnızca en azından o kadar büyük olduklarını umursanız , tavsiyeniz yaygın modern PC / sunucu platformları için geçerlidir.
Tony Delroy

8
O CHAR_BIT> 8. örn DSP'ler genelde 16 veya 32 bandında CHAR_BIT (örn görmesine var sadece eski cray makineleri olmadığını Not bu )
nos

2
@nos: Bağlantı için teşekkürler. Oddball vakaları için modern, güncel sistemlerin tanımlanması çok yararlıdır. Meraktan, bu makinelerde ayarlanan kod nedir? Kod kümesi UTF-16 ise, 0xFFFF geçerli bir karakter değildir ve kod kümesi bir ISO 8859-x kod kümesi ise, yine 0xFFFF geçerli bir karakter değildir (0x00 ile 0xFF arasındaki karakter kodları geçerlidir). Henüz EOF'u tespit etmede bir sorun olduğuna ikna olmadım, ancak kesinlikle dikkat edilmesi gereken bir yer var ve muhtemelen int get_char(FILE *fp, char *c)EOF veya 0 döndüren bir işlevi yazmak ve kullanmak için *c.
Jonathan Leffler

2
@joelw: C11, "int" değerinin 32 bit veya daha küçük olduğu platformlarda uint32_t x=1,y=2;değeri x-y4294967295 ve "int" değerinin 33 bit veya daha büyük olduğu platformlarda -1 olması gerektiğini gerektirir . Ayrıca, x*y"int" 32 bit veya daha küçükse x ve y'nin tüm değerleri için modüler aritmetik ve 65 bit veya daha büyükse konvansiyonel aritmetik kullanılarak değerlendirilmesi gerekir, ancak büyük değerlerle neler olabileceğine dair herhangi bir gereklilik getirmez "int" 33 ila 64 bit ise x ve y.
supercat

88

Uygulamada böyle bir şey yok. Genellikle std::size_tmevcut mimaride işaretsiz yerel tamsayı boyutunu temsil etmeyi bekleyebilirsiniz . yani 16 bit, 32 bit veya 64 bit, ancak bu cevabın yorumlarında belirtildiği gibi her zaman böyle değildir.

Diğer tüm yerleşik tipler gittikçe, gerçekten derleyiciye bağlıdır. En son C ++ standardının mevcut çalışma taslağından alınan iki alıntı:

Beş standart imzalı tamsayı türü vardır: imzalı karakter, kısa int, int, uzun int ve uzun uzun int. Bu listede, her tür, listede öncekinden daha az depolama alanı sağlar.

Standart imzalı tamsayı türlerinin her biri için karşılık gelen (ancak farklı) bir standart imzasız tamsayı türü vardır: imzasız karakter, imzasız kısa int, imzasız int, imzasız uzun int ve imzasız uzun uzun int, bunların her biri aynı miktarda depolama ve aynı hizalama gereksinimlerine sahiptir.

İsterseniz bu temel türlerin boyutunu statik olarak (derleme zamanı) iddia edebilirsiniz. Sizeof varsayımları değişirse, insanları kodunuzu taşıma konusunda düşünecekleri konusunda uyarır.


7
iyi yazı. gerekli olan başka bir şey, aşağıdaki en az bit boyutudur (c89 / c99'da sınırlar.h ile birlikte belgelenir ve c ++ tarafından alınır): char> = 8, short ve int> = 16, long> = 32.
Johannes Schaub - litb

1
Ayrıca, 8 bitlik bir AVR platformunda size_t 8 bit değil 16 olacaktır, çünkü işaretçi ve int boyutları 16 bittir. Dolayısıyla, işlemci yerel veri boyutu size_t ile ilişkili değildir.
Robotbugs

80

Standart var.

C90 standardı bunu gerektirir

sizeof(short) <= sizeof(int) <= sizeof(long)

C99 standardı bunu gerektirir

sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

İşte C99 teknik özellikleri . Sayfa 22 farklı integral tiplerinin boyutlarını detaylandırmaktadır.

İşte Windows platformları için int türü boyutları (bit):

Type           C99 Minimum     Windows 32bit
char           8               8
short          16              16
int            16              32
long           32              32
long long      64              64

Taşınabilirlikle ilgileniyorsanız veya türün adının boyutu yansıtmasını istiyorsanız <inttypes.h>, aşağıdaki makroların bulunduğu başlığa bakabilirsiniz :

int8_t
int16_t
int32_t
int64_t

int8_t8 bit, int16_t16 bit vb.


8
Küçük nitpick: standart sizeof(long) < sizeof(long long)simetrikin aksine nerede diyor sizeof(long) <= sizeof(long long)?
Jonathan Leffler

2
@JonathonLeffler - bkz. C99 5.2.4.2.1 - Tamsayı tiplerinin boyutları. minsizeof (int) == 16-bit, minsizeof (uzun) == 32-bit, minsizeof (uzun uzun) == 64-bit. Ben hiçbir maxsizeof (tip) belirtildiği gibi doğru <= olduğunu düşünüyorum.
Jesse Chisholm

Benzer şekilde sizeof (float) <= sizeof (double) <= sizeof (long double). C99 7.12 paragraf 2'ye göre
Jesse Chisholm

38

Sabit boyut türlerine ihtiyacınız varsa, stdint.h dosyasında tanımlanan uint32_t (işaretsiz tam sayı 32 bit) gibi türleri kullanın . Bunlar C99'da belirtilmiştir .


10
Belirtilir ancak zorunlu değildir.
dreamlax

2
@dreamlax Hangi platformlar içermiyor?
Levi Morrison

3
@LeviMorrison: Gerekli formda olmayan platformlar. CHAR_BIT == 16Örneğin, sahip olan bir platform sahip olmayacaktır int8_t. Herhangi bir platform ikinin tamamlayıcısı olmaz kullanmayan herhangi (ikiye tümleme standardının gerektirdiği gibi) bunlardan.
DevSolar

36

Güncelleme: C ++ 11, TR1 tiplerini resmen standarda getirdi:

  • uzun uzun int
  • imzasız uzun uzun int

Ve "boyutlu" türleri <cstdint>

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (ve imzasız meslektaşları).

Artı:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • Ayrıca imzasız meslektaşları.

Bu türler, en az belirtilen bit sayısına sahip en küçük tamsayı türlerini temsil eder. Benzer şekilde, en azından belirtilen sayıda bite sahip "en hızlı" tamsayı türleri vardır:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • Ayrıca imzasız sürümler.

"Hızlı" ne anlama geliyorsa, uygulamaya bağlıdır. Tüm amaçlar için en hızlı olması da gerekmez.


Bu artık C ++ 11 standardının bir parçası.
Jaan

2
"hızlı" sadece donanım mimarisine göre düzenlenmiş demektir. Kayıtlar 16 bit ise, int_fast8_t 16 bitlik bir değerdir. Kayıtlar 32-bit ise, int_fast8_t ve int_fast16_t ikisi de 32-bit değerlerdir. vb. C99 bölüm 7.18.1.3 paragraf 2'ye bakınız.
Jesse Chisholm

19

C ++ Standart şöyle der:

3.9.1, §2:

Beş imzalı tamsayı türü vardır: "işaretli karakter", "kısa int", "int", "uzun int" ve "uzun uzun int". Bu listede, her tür, listede öncekinden daha az depolama alanı sağlar. Düz iç kısımlar, yürütme ortamının mimarisi tarafından önerilen doğal boyuta sahiptir (44); diğer imzalı tamsayı türleri özel ihtiyaçları karşılamak için verilmiştir.

(44) , başlıkta tanımlandığı gibi INT_MIN ve INT_MAX aralığında herhangi bir değer içerebilecek kadar büyüktür <climits> .

Sonuç: Hangi mimaride çalıştığınıza bağlıdır. Diğer varsayımlar yanlıştır.


12

Hayır, tip boyutları için standart yoktur. Standart sadece şunları gerektirir:

sizeof(short int) <= sizeof(int) <= sizeof(long int)

Sabit boyuttaki değişkenleri istiyorsanız yapabileceğiniz en iyi şey, aşağıdaki gibi makroları kullanmaktır:

#ifdef SYSTEM_X
  #define WORD int
#else
  #define WORD long int
#endif

Ardından değişkenlerinizi tanımlamak için WORD kullanabilirsiniz. Bunu sevdiğimden değil ama en taşınabilir yol.


4
Sorun, WORD programın etrafına sabit bir boyuta bağlı olmayan alanlara yayılmasıdır (bazı windows kodlarına bakın). 16 bit'ten 32 bit sisteme geçerken öğrendiğim gibi, WORD'ün çözmesi gereken aynı problemle karşılaşıyorsunuz.
lilburne

@liburne Tabii ki WORD'ü sadece sabit boyutlu bir değişkene ihtiyacınız olduğunda kullanmalısınız, örneğin bir dosyadan / dosyaya okuma / yazma gibi. Bir kod parçası gerçekten sabit bir boyuta bağımlı değilse, normal "int" değişkenlerini kullanmalısınız.
Emiliano

3
Taşınabilir boyutlar elde etmek için yapabileceğiniz en iyi şey#include <boost/cstdint.hpp>
kizzx2

11

Kendi "standart" ımızı oluşturabilmemiz için tür için eşanlamlı bir tanım tanımlamamıza izin verilmiştir.

Sizeof (int) == 4 olan bir makinede şunları tanımlayabiliriz:

typedef int int32;

int32 i;
int32 j;
...

Bu yüzden kodu aslında int uzunluğunun 4 olduğu farklı bir makineye aktardığımızda, int'in tek oluşumunu yeniden tanımlayabiliriz.

typedef long int int32;

int32 i;
int32 j;
...

1
Standart başlık <stdint.h>(C99 ve üstü ve hangi C ++ standardı C kütüphanesinin C99 sürümünü benimsemişse) bu gerekli değildir.
Keith Thompson

8

Kayan nokta sayıları için bir standart (IEEE754) vardır : şamandıralar 32 bit ve çiftler 64'tür. Bu bir C ++ standardı değil, bir donanım standardıdır, bu nedenle derleyiciler teorik olarak şamandıra ve başka bir boyuta iki katını tanımlayabilirler, ancak pratikte ' Farklı bir şey kullanan bir mimari görmedim.


2
Ancak, IEEE 754 (diğer adıyla IEC 559) ile uyumluluk C ++ içinde isteğe bağlıdır (muhtemelen C de olabilir, ancak emin değilim). Bkz. Std :: numeric_limits :: is_iec559.
Drew Hall

1
Sonra TMS320C28xx DSP'lerle için TI derleyici görmedim doubleaynı boyuta sahip float(ve intaynı charikisi de 16 bit olduğunu). Ama 64 bitleri var long double.
starblue

7

Bir standart vardır ve çeşitli standart dokümanlarında (ISO, ANSI ve ne değilse) belirtilmiştir.

Wikipedia, çeşitli türleri ve saklayabilecekleri maksimum değeri açıklayan harika bir sayfaya sahiptir: Bilgisayar Biliminde Tamsayı.

Ancak standart bir C ++ derleyicisiyle bile, aşağıdaki kod snippet'ini kullanarak nispeten kolayca öğrenebilirsiniz:

#include <iostream>
#include <limits>


int main() {
    // Change the template parameter to the various different types.
    std::cout << std::numeric_limits<int>::max() << std::endl;
}

İçin Belgeler std :: numeric_limits bulunabilir Roguewave . Çeşitli sınırları bulmak için çağırabileceğiniz diğer komutların birçoğunu içerir. Bu, boyutu ileten herhangi bir rastgele tipte kullanılabilir, örneğin std :: streamsize.

John'un cevabı, tutulması garanti edildiği için en iyi açıklamayı içerir. Hangi platformda olursanız olun, her türün kaç biti İÇERMESİ gerektiği konusunda daha ayrıntılı bilgi veren başka bir iyi sayfa var: standartta tanımlanan int türleri .

Umarım bu yardımcı olur!



7

Kullanabilirsiniz:

cout << "size of datatype = " << sizeof(datatype) << endl;

datatype = int, long intVb yazdığınız hangisi veri türü boyutunu görmek mümkün olacak.


7

Farklı mimariler ve farklı derleyiciler için yerleşik türler söz konusu olduğunda, çıktısını görmek için derleyicinizle mimarinizde aşağıdaki kodu çalıştırın. Aşağıda Ubuntu 13.04 (Raring Ringtail) 64 bit g ++ 4.7.3 çıkışımı gösteriyor . Ayrıca, aşağıda neyin cevaplandığını da unutmayın, bu nedenle çıktı bu şekilde sipariş edilir:

"Beş standart imzalı tamsayı türü vardır: imzalı karakter, kısa int, int, uzun int ve uzun uzun int. Bu listede, her tür en az listede yer alan depolama alanını sağlar."

#include <iostream>

int main ( int argc, char * argv[] )
{
  std::cout<< "size of char: " << sizeof (char) << std::endl;
  std::cout<< "size of short: " << sizeof (short) << std::endl;
  std::cout<< "size of int: " << sizeof (int) << std::endl;
  std::cout<< "size of long: " << sizeof (long) << std::endl;
  std::cout<< "size of long long: " << sizeof (long long) << std::endl;

  std::cout<< "size of float: " << sizeof (float) << std::endl;
  std::cout<< "size of double: " << sizeof (double) << std::endl;

  std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}


size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8

sizeof(char)dahil edilmemelidir.
Ven

3

Belirtildiği gibi, boyut mevcut mimariyi yansıtmalıdır. limits.hMevcut derleyicinizin bir şeyleri nasıl ele aldığını görmek istiyorsanız etrafta bir zirve yapabilirsiniz .


Teşekkürler, ama myselft (64 bit gibi) olmayan mimariler için boyutları bilmek istiyorum. Bu eğitim sadece 32 bit mimarileri hakkında konuşmak ...
Jérôme

2

Diğerlerinin yanıtladığı gibi, "standartlar" ın tamamı ayrıntıların çoğunu "uygulama tanımlı" olarak bırakır ve yalnızca "char" türünün "char_bis" genişliğinde ve "char <= short <= int <= long < = uzun uzun "(şamandıra ve çift, IEEE kayan nokta standartlarıyla oldukça tutarlıdır ve uzun çift tipik olarak çift ile aynıdır - ancak daha güncel uygulamalarda daha büyük olabilir).

Çok spesifik ve kesin değerlere sahip olmama nedenlerinin bir kısmı, C / C ++ gibi dillerin çok sayıda donanım platformuna taşınabilir olacak şekilde tasarlanmasıdır - "char" sözcük boyutunun 4 bit olabileceği bilgisayar sistemleri dahil veya 7 bitlik, hatta ortalama ev bilgisayarı kullanıcısının maruz kaldığı "8- / 16- / 32- / 64-bit" bilgisayarlardan başka bir değer. (Buradaki kelime boyutu, sistemin normalde kaç bit genişliğinde çalıştığı anlamına gelir - Yine, ev bilgisayarı kullanıcılarının beklediği gibi her zaman 8 bit değildir.)

Belirli sayıda bitin gerçekten bir nesnesine (integral değeri temsil eden bir dizi bit anlamında) ihtiyacınız varsa, çoğu derleyicinin bunu belirtmek için bazı yöntemleri vardır; Ancak, genellikle ame şirketi tarafından yapılan derleyiciler arasında değil, farklı platformlar için taşınabilir. Bazı standartlar ve uygulamalar (özellikle limit.h ve benzeri) çoğu derleyicinin belirli bir değer aralığı için en uygun türün belirlenmesine destek olacak, ancak kullanılan bit sayısını destekleyecek kadar yaygındır. (Yani, 0 ile 127 arasında değerleri tutmanız gerektiğini biliyorsanız, derleyicinizin "int8" 8 bitlik bir türü desteklediğini belirleyebilirsiniz; bu, istenen tüm aralığı tutmak için yeterince büyük olacaktır, ancak 7-bit için tam olarak eşleşen "int7" türü.)

Not: Birçok Un * x kaynak paketinde, derleyicinin / sistemin yeteneklerini araştıracak ve uygun bir Makefile ve config.h çıktısı veren "./configure" komut dosyası kullanılmıştır. Nasıl çalıştıklarını ve derleyici / sistem yeteneklerini nasıl incelediklerini görmek için bu komut dosyalarından bazılarını inceleyebilir ve yol gösterimlerini takip edebilirsiniz.


1

Saf bir C ++ çözümüyle ilgileniyorsanız, bit boyutlarına göre türleri derlemek için şablonlar ve yalnızca C ++ standart kodunu kullandım. Bu, çözümü derleyiciler arasında taşınabilir hale getirir.

Arkasındaki fikir çok basit: char, int, kısa, uzun, uzun uzun (imzalı ve imzasız sürümler) türlerini içeren bir liste oluşturun ve listeyi tarayın ve numeric_limits şablonunu kullanarak verilen boyuta sahip türü seçin.

Bu başlık dahil 8 tip stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.

Bazı türler temsil edilemiyorsa, o başlıkta bildirilen stdtype :: null_type olarak değerlendirilir.

AŞAĞIDAKİ KOD GARANTİ OLMADAN VERİLİR, LÜTFEN ÇİFT KONTROL EDİN.
ÇOK METAPROGRAMMING'DE YENİ, BU KODU DÜZENLEMEK VE DÜZELTMEKTEDİR.
DevC ++ ile test edildi (böylece 3.5 civarında bir gcc sürümü)

#include <limits>

namespace stdtype
{
    using namespace std;


    /*
     * THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
     * YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS 
     * DECLARED/USED.
     *
     * PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
     */
    class null_type{};

    /*
     *  Template for creating lists of types
     *
     *  T is type to hold
     *  S is the next type_list<T,S> type
     *
     *  Example:
     *   Creating a list with type int and char: 
     *      typedef type_list<int, type_list<char> > test;
     *      test::value         //int
     *      test::next::value   //char
     */
    template <typename T, typename S> struct type_list
    {
        typedef T value;
        typedef S next;         

    };




    /*
     * Declaration of template struct for selecting a type from the list
     */
    template <typename list, int b, int ctl> struct select_type;


    /*
     * Find a type with specified "b" bit in list "list"
     *
     * 
     */
    template <typename list, int b> struct find_type
    {   
        private:
            //Handy name for the type at the head of the list
            typedef typename list::value cur_type;

            //Number of bits of the type at the head
            //CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
            enum {cur_type_bits = numeric_limits<cur_type>::digits};

        public:
            //Select the type at the head if b == cur_type_bits else
            //select_type call find_type with list::next
            typedef  typename select_type<list, b, cur_type_bits>::type type;
    };

    /*
     * This is the specialization for empty list, return the null_type
     * OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
     * (ie search for type with 17 bits on common archs)
     */
    template <int b> struct find_type<null_type, b>
    {   
        typedef null_type type;

    };


    /*
     * Primary template for selecting the type at the head of the list if
     * it matches the requested bits (b == ctl)
     *
     * If b == ctl the partial specified templated is evaluated so here we have
     * b != ctl. We call find_type on the next element of the list
     */
    template <typename list, int b, int ctl> struct select_type
    {   
            typedef  typename find_type<typename list::next, b>::type type; 
    };

    /*
     * This partial specified templated is used to select top type of a list
     * it is called by find_type with the list of value (consumed at each call)
     * the bits requested (b) and the current type (top type) length in bits
     *
     * We specialice the b == ctl case
     */
    template <typename list, int b> struct select_type<list, b, b>
    {
            typedef typename list::value type;
    };


    /*
     * These are the types list, to avoid possible ambiguity (some weird archs)
     * we kept signed and unsigned separated
     */

    #define UNSIGNED_TYPES type_list<unsigned char,         \
        type_list<unsigned short,                           \
        type_list<unsigned int,                             \
        type_list<unsigned long,                            \
        type_list<unsigned long long, null_type> > > > >

    #define SIGNED_TYPES type_list<signed char,         \
        type_list<signed short,                         \
        type_list<signed int,                           \
        type_list<signed long,                          \
        type_list<signed long long, null_type> > > > >



    /*
     * These are acutally typedef used in programs.
     * 
     * Nomenclature is [u]intN where u if present means unsigned, N is the 
     * number of bits in the integer
     *
     * find_type is used simply by giving first a type_list then the number of 
     * bits to search for.
     *
     * NB. Each type in the type list must had specified the template 
     * numeric_limits as it is used to compute the type len in (binary) digit.
     */
    typedef find_type<UNSIGNED_TYPES, 8>::type  uint8;
    typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
    typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
    typedef find_type<UNSIGNED_TYPES, 64>::type uint64;

    typedef find_type<SIGNED_TYPES, 7>::type    int8;
    typedef find_type<SIGNED_TYPES, 15>::type   int16;
    typedef find_type<SIGNED_TYPES, 31>::type   int32;
    typedef find_type<SIGNED_TYPES, 63>::type   int64;

}

0
unsigned char bits = sizeof(X) << 3;

Nerede Xbir edilir char, int, longvb .. size boyutunu verecek Xbit.


1
bir karakter her zaman 8 bit değildir, bu nedenle ifadeniz 8 bitlik karakter olmayan mimarilerde çalışmaz . Sadece sizeof(type)*CHAR_BITtutar
phuclv

CHAR_BIT8 bit olduğu garanti edilse bile << 3, sadece gizli bir yazma yolu * 8veya * CHAR_BIT.
Keith Thompson

0

Alex B'den C ++ standardı bayt cinsinden integral türlerin boyutunu belirtmez, ancak tutabilmeleri gereken minimum aralıkları belirtir. Gerekli aralıktan bit cinsinden minimum boyutu çıkarabilirsiniz. Bundan bayt cinsinden minimum boyutu ve bir bayttaki bit sayısını tanımlayan CHAR_BIT makrosunun değerini çıkarabilirsiniz (en belirsiz platformlar hariç 8'dir ve 8'den az olamaz).

Karakter için ek bir kısıtlama, boyutunun her zaman 1 bayt veya CHAR_BIT bit (dolayısıyla ad) olmasıdır.

Standardın gerektirdiği minimum aralıklar (sayfa 22):

ve Veri Türü Aralıkları:

imzalı char: -127 ila 127 (not, -128 ila 127 değil; 1'in tamamlayıcı platformları barındırır) imzasız char: 0 ila 255 "düz" char: -127 ila 127 veya 0 ila 255 (varsayılan char imzasına bağlıdır) kısa: -32767 ila 32767 imzasız kısa: 0 ila 65535 imzalı int: -32767 ila 32767 imzasız int: 0 ila 65535 imzalı uzun: -2147483647 ila 2147483647 imzasız uzun: 0 ila 4294967295 uzun imzalı: -9223372036854775807 ila 9223372036854775807 0 ila 18446744073709551615 Bir C ++ (veya C) uygulaması, bir türün boyutunu sizeof (tip) bayt cinsinden herhangi bir değere kadar herhangi bir değere tanımlayabilir

sizeof (type) * CHAR_BIT ifadesi, gerekli aralıkları içerecek kadar bit sayısı olarak değerlendirilir ve türün sırası hala geçerlidir (örneğin sizeof (int) <= sizeof (uzun)). Gerçek uygulamaya özgü aralıklar, C'deki başlıkta veya C ++ 'da (veya daha iyi, şablonlanmış std :: numeric_limits in header) bulunabilir.

Örneğin, int için maksimum aralığı şu şekilde bulabilirsiniz:

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++:

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();

Bu doğrudur, ancak şunu da söylediniz: char: 1 bayt kısa: 2 bayt int: 4 bayt uzunluğunda: 4 bayt kayan: 4 bayt çift: 8 bayt

32 bit mimariler hala varsayılan ve en çok kullanılanlar olduğundan ve belleğin daha az kullanılabilir olduğu 32 bitlik günlerden beri bu standart boyutları korudular ve geriye dönük uyumluluk ve standardizasyon için aynı kaldı. 64 bit sistemler bile bunları kullanma eğilimindedir ve kapsamları / modifikasyonları vardır. Daha fazla bilgi için lütfen buna başvurun:

http://en.cppreference.com/w/cpp/language/types


0

Buradaki diğer tüm cevapların neredeyse sadece integral türlerine odaklandığını fark ederken, soru soran da kayan noktaları sordu.

C ++ standardının gerektirdiğini düşünmüyorum, ancak bu günlerde en yaygın platformlar için derleyiciler genellikle kayan nokta sayıları için IEEE754 standardını takip ediyor. Bu standart, dört tür ikili kayan nokta (C ++ derleyicilerinde hiç destek görmediğim bazı BCD biçimlerinin yanı sıra) belirtir:

  • Yarı hassasiyet (binary16) - 11 bitlik anlamlı, üs aralığı -14 ila 15
  • Tek duyarlıklı (binary32) - 24-bit anlamlı, üs -126 ila 127
  • Çift kesinlik (binary64) - 53-bit önemi, -1022 ila 1023 üs aralığı
  • Dörtlü hassasiyet (ikili128) - 113 bit anlamlı, üs aralığı -16382 ila 16383

Peki bu nasıl C ++ tipleri ile eşleşir? Genellikle floattek hassasiyet kullanır; böylece sizeof(float) = 4,. Sonra doubleçift ​​kesinlik kullanır (bunun ismin kaynağı olduğuna inanıyorum double) velong double çift ​​veya dörtlü hassasiyet olabilir (sistemimde dörtlüdür, ancak 32 bit sistemlerde çift olabilir). Yarı hassas kayan noktalar sunan herhangi bir derleyici bilmiyorum.

Özetle, bu olağan:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 veya 16

Jeff'in neden ihtiyaç duyduğundan daha fazla bayt kullandığını merak etmenin bir parçası olarak bu soruya geldiğim komik.
Aniruddha Varma


-2

OpenGL , Qt vb. Gibi kütüphaneler tarafından sağlanan değişkenleri kullanabilirsiniz .

Örneğin Qt , Qint8 (Qt tarafından desteklenen tüm platformlarda 8 bit olması garanti edilir), qint16, qint32, qint64, quint8, quint16, quint32, quint64 vb.


1
Soruya

-8

64 bit makinede:

int: 4
long: 8
long long: 8
void*: 8
size_t: 8

2
Bazı 64 bit makinelerde int8 bayt vardır, ancak diğeri garanti edilmez. Bunun charsadece 8 bit olması gerektiğini söyleyen hiçbir şey yok . sizeof(void*)==464 bit olmasına rağmen sahip olmasına izin verilir .
skyking

-10

Boyuta göre dört tür tamsayı vardır:

  • kısa tamsayı: 2 bayt
  • uzun tamsayı: 4 bayt
  • uzun uzun tamsayı: 8 bayt
  • integer: derleyiciye bağlıdır (16 bit, 32 bit veya 64 bit)

11
Yanlış, hepsi mimariden, diğer cevaplardan birinde açıklanan minimum aralıklar ile bağlıdır. Hiçbir şey için bir uygulama durur short, intve long32 bitlik tamsayılar.
Matteo Italia

Türler için doğru isimleri bile kullanmadınız. Adlar int"tamsayı" kelimesini değil , anahtar kelimeyi kullanır .
Keith Thompson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.