C boyutu “int” 2 bayt mı yoksa 4 bayt mı?


169

C'deki bir Tamsayı değişkeni 2 bayt mı yoksa 4 bayt mı? Bağlı olduğu faktörler nelerdir?

Ders kitaplarının çoğu tamsayı değişkenlerinin 2 bayt içerdiğini söylüyor. Ama bir tamsayılar dizisinin birbirini izleyen adreslerini yazdıran bir program çalıştırdığımda 4 farkını gösteriyor.



1
intbirkaç tamsayı türünden sadece biridir . "Tamsayı" boyutunu sordunuz; muhtemelen boyutu hakkında sormak istedim int.
Keith Thompson

3
Ve daha iyi ders kitapları bulmalısınız. A'nın int2 bayt (a) olduğunu söyleyen bir ders kitabı muhtemelen eski bir sisteme atıfta bulunur ve (b) boyutun bir sistemden diğerine değişeceğini netleştiremez. C ile ilgili en iyi kitap, Kernighan ve Ritchie'nin "C Programlama Dili" dir, ancak bazı programlama deneyimini varsayar. Ayrıca bkz . Comp.lang.c SSS'nin 18.10. Sorusu .
Keith Thompson

2
#define int int64_t64 bit bir platformda deneyin , bu yüzden de. Sadece kullan sizeof. ;-)
netcoder

Yanıtlar:


183

Eşit olduğunu biliyorum sizeof(int). Bir boyutu intgerçekten derleyiciye bağlıdır. İşlemcilerin 16 bit olduğu günlerde int2 bayt oldu. Günümüzde, 32 bit ve 64 bit sistemlerde çoğunlukla 4 bayt.

Yine de, kullanmak sizeof(int), programın yürütüldüğü belirli bir sistem için bir tamsayı boyutunu elde etmenin en iyi yoludur.

EDIT:int Çoğu 64-bit sistemlerde 8 bayt olan yanlış deyimi düzeltildi . Örneğin, 64 bit GCC'de 4 bayttır.


31
@RajivPrathap: Derleyiciye bağlı, ancak derleyici de makineye bağlı olup olmadığına karar veriyor. :)
user541686

2
Ön işlemci için boyuta ihtiyacınız varsa, INT_MAX gibi önceden tanımlanmış makroları kontrol edebilirsiniz. Değer kodunuz tarafından beklenen değer değilse, geçerli derleyici / platform birleşiminde int bayt boyutu farklıdır.
Walt Satıcıları

3
Sadece makineye bağlı değil, aynı zamanda makinede çalışan işletim sistemine de bağlıdır. Örneğin, Win64'te uzun 4 bayt, Linux64'te uzun 8 bayttır.
Cem Kalyoncu

9
yanlış. 64-bit sistemlerde int hala 4 baytlık en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
phuclv

7
sizeof(int)herhangi bir değer olabilir 1. Bir baytın 8 bit olması gerekmez ve bazı makinelerde 8 bit adreslenebilir bir birim yoktur (temel olarak standartta bir bayt tanımıdır ). Daha fazla bilgi olmadan cevap doğru değil.
Bu site için çok dürüst

103

Bu, C'de başlangıçta kafa karıştırıcı olabilecek noktalardan biridir, ancak C standardı yalnızca , destekleneceği garanti edilen tamsayı türleri için minimum aralığı . int16 bit gerektiren -32767 ila 32767'yi tutabileceği garanti edilmektedir. Bu durumda, int2 bayttır. Bununla birlikte, birçok modern derleyicinin int32 bit (aynı zamanda 4 bayt da her yerde olduğu anlamına gelir) yaptığını göreceğiniz gibi, uygulamalar bu minimumun ötesine geçmekte özgürdür .

Kitabınızın 2 bayt söylemesinin nedeni büyük olasılıkla eski olmasıdır. Bir zamanlar bu normdu. Genel olarak, kullandığınız sizeofplatformda kaç bayt olduğunu bulmanız gerekiyorsa her zaman operatörü kullanmalısınız.

Bunu ele almak için C99, belirli bir boyutlu tamsayı (örneğin int16_tveya) açıkça isteyebileceğiniz yeni türler ekledi int32_t. Bundan önce, belirli bir genişlikte bir tam sayı elde etmenin evrensel bir yolu yoktu (çoğu platform, platform başına benzer türler sağlamasına rağmen).


7
@nevanking: İkinin tamamlayıcı makinesinde (ki bildiğim her makine ...), evet. Ancak, C bunun böyle olacağını garanti etmez.
FatalError

@nevanking C için tamamen yeniyim, ancak 32767 değil mi? Aksi takdirde başka bir bit | byte kullanıyor olurdu? Düşünün, 3 basamak (0 veya 1) tutabilirim, böylece 000'dan 111'e (ondalık 7'dir) gidebilirim. 7, 2 üssünden hemen önce. 8'e (1000) kadar gidebilseydim, bu 4 basamağı 15'e kadar kullanabilirdim! 32767 gibi, 2 bitinin hemen önündedir, mevcut tüm bitleri | baytları tüketir.
RGS

3
@RSerrao Ben de bir C uzmanı değilim ama pozitif sayılar için AFAIK, maksimum negatif sayıdan daha az. Yani -8 ila 7, -256 ila 255 vb. Negatif sayılar sıfırı saymak zorunda değildir.
nevan king

1
"16 bit. Bu durumda, int, 2 bayttır" yanlış olabilir, CHAR_BIT 16 ise, sizeof (int) 1 bayt (veya char) olabilir.
12431234123412341234123

6
@nevanking: yalnızca 2'nin imzalı için tamamlayıcı temsilini varsayarsanız int. C bu varsayımı yapmaz. 1'in tamamlayıcı ve işaret büyüklüğü sistemleri -3276816 bitte temsil edilemez ; daha ziyade, sıfır için iki temsilleri vardır (pozitif ve negatif). Bir asgari aralık yüzden intolduğunu [-32767..32767].
John Bode

33

Bunun kesin bir cevabı yok. Platforma bağlıdır. Uygulama tanımlıdır. 2, 4 veya başka bir şey olabilir.

Arkasındaki fikir int , verilen platformdaki doğal "kelime" boyutuyla eşleşmesi gerekiyordu: 16 bit platformlarda 16 bit, 32 bit platformlarda 32 bit, 64 bit platformlarda 64 bit, fikri anlıyorsunuz. Ancak, geriye dönük uyumluluk amacıyla bazı derleyiciler int64-bit platformlarda bile 32-bit'e yapışmayı tercih eder .

int16 bitlik kelime boyutuna sahip gömülü bir platform kullanmıyorsanız , 2 baytlık süre çoktan gitti (16 bit platformlar?). Ders kitaplarınız muhtemelen çok eskidir.


2
The idea behind int was that it was supposed to match the natural "word" size on the given platform- Aradığım şey buydu. Sebebi ne olabilir? Özgür bir dünyada, int bellekte herhangi bir sayıda ardışık bayt işgal edebilir mi? 8, 16 whatever
bholagabbar

19

Bu sorunun cevabı kullandığınız platforma bağlıdır.
Ancak platformdan bağımsız olarak, aşağıdaki türleri güvenilir bir şekilde kabul edebilirsiniz:

 [8-bit] signed char: -127 to 127
 [8-bit] unsigned char: 0 to 255
 [16-bit]signed short: -32767 to 32767
 [16-bit]unsigned short: 0 to 65535
 [32-bit]signed long: -2147483647 to 2147483647
 [32-bit]unsigned long: 0 to 4294967295
 [64-bit]signed long long: -9223372036854775807 to 9223372036854775807
 [64-bit]unsigned long long: 0 to 18446744073709551615

3
Birisi yayınınızı aralıkları "düzeltmek" için düzenledi, ancak düzenlemenizin amacınızı yeterince yansıtıp yansıtmadığından emin değilim. Bir ikisinin tamamlayıcı uygulamasını varsayar, ki bu çoğu durumda geçerli olur, ancak hepsi değil. Cevabınız özellikle uygulama bağımlılığına işaret ettiğinden, düzenlemenin muhtemelen yanlış olduğunu düşünüyorum. Kabul ediyorsanız, lütfen düzenlemeyi geri aldığınızdan emin olun.
Cody Gray

1
@ k06a düzenlemeniz yanlış . Orijinal aralıkları özellikle 2 tamamlayıcı aralığa değiştirdiniz - bunlar C standardında belirtilenler değil .
Antti Haapala

@CodyGray Bu son 3 yıldır 1 tamamlayıcı uyumlu ve OP bir şey söylemeyen ileri geri dalgalanıyor, bu yüzden "düzeltme aralıkları" ile 2 tamamlayıcı değiştiren bir düzenleme geri döndü, çünkü "güvenilir bir şekilde kabul edebilirsiniz" diyor hala doğru değil.
Antti Haapala

13

C'deki bir Tamsayı değişkeni 2 bayt mı yoksa 4 bayt mı?

Bu, kullandığınız platforma ve derleyicinizin nasıl yapılandırıldığına bağlıdır. Tek yetkili cevap, sizeofözel durumunuzda bir tam sayının ne kadar büyük olduğunu görmek için operatörü kullanmaktır .


Bağlı olduğu faktörler nelerdir?

Aralık , boyuttan ziyade en iyi şekilde düşünülebilir . Her ikisi de pratikte farklılık gösterecektir, ancak değişken türleri aralığa göre göreceğimiz kadar büyüklükte seçmek çok daha aptalca dayanıklıdır. Standardın bizi tamsayı türlerimizi boyuttan ziyade aralığa göre seçmeye teşvik ettiğine dikkat etmek de önemlidir , ancak şimdilik standart uygulamayı görmezden gelelim ve merakımızın , baytları ve tamsayı temsilini keşfetmesine izin verelim ... tavşan deliği ve kendimiz görün ...sizeofCHAR_BIT


sizeof, bayt ve CHAR_BIT

C standardından alınan (yukarıdaki ile bağlantılı) aşağıdaki ifade, bunu geliştirilebileceğini düşünmediğim kelimelerle açıklamaktadır.

sizeofOperatör bir ekspresyon ya da bir tür parantez içinde adı olabilir onun işlenen (bayt) boyutu, elde edilir. Boyut, işlenen türünden belirlenir.

Açık bir anlayış varsaymak bizi bayt hakkında bir tartışmaya götürecektir . Genellikle bir baytın sekiz bit olduğu varsayılır, gerçekte CHAR_BITsize bir baytta kaç bit olduğunu söyler . Bu , ortak iki (veya dört) bayt tamsayı hakkında konuşurken dikkate alınmayan nüanslardan sadece bir diğeri .

Şimdiye kadar işleri tamamlayalım:

  • sizeof => bayt cinsinden boyut ve
  • CHAR_BIT => bayttaki bit sayısı

Böylece, sisteminize bağlı olarak, sıfırdan büyük herhangi bir değer sizeof (unsigned int)olabilir (sadece 2 veya 4 değil), 16 gibi, o zaman tek bir (onaltı bit) bir bayt , standartları (aşağıda alıntılanmıştır). Bu her zaman yararlı bir bilgi değil, değil mi? Daha derine inelim ...CHAR_BIT


Tamsayı gösterimi

C standardı CHAR_BIT, burada tüm standart tamsayı türleri (ve de fwiw) için minimum hassasiyeti / aralığı belirtir . Bundan , değeri saklamak için kaç bitin gerekli olduğu için bir minimum türetebiliriz , ancak değişkenlerimizi aralıklara göre seçebiliriz . Bununla birlikte, bu cevap için gereken detayların büyük bir kısmı burada bulunmaktadır. Örneğin, standardın (en az) on altı bit depolama alanı gerektirmesi:unsigned int

UINT_MAX                                65535 // 2¹⁶ - 1

Bu nedenle unsigned int( en azından ) 16 bit gerektirdiğini görebiliriz , bu da iki baytı aldığınız yerdir ( CHAR_BIT8 olduğu varsayılır ) ... ve daha sonra bu sınır arttığında 2³² - 1, insanlar bunun yerine 4 bayt belirtiyordu . Bu, gözlemlediğiniz fenomenleri açıklar:

Ders kitaplarının çoğu tamsayı değişkenlerinin 2 bayt içerdiğini söylüyor. Ama bir tamsayılar dizisinin birbirini izleyen adreslerini yazdıran bir program çalıştırdığımda 4 farkını gösteriyor.

Taşınabilir olmayan C'yi öğreten eski bir ders kitabı ve derleyici kullanıyorsunuz; ders kitabınızı yazan yazar farkında bile olmayabilir CHAR_BIT. Sen olmalıdır için ders kitabı (ve derleyici) yükseltme ve BT sürekli gelişen bir alan kalmak gerektiğini olduğunu hatırlamak için çaba öncesinde rekabet ettiğini ... olsa Yeter bu konuda hiç; Bakalım tamsayı baytlarının sakladığı diğer taşınabilir olmayan sırlar ne ...

Değer bitleri , yaygın yanılgıların dikkate alındığı şeydir. Yukarıdaki örnek, unsignedtipik olarak yalnızca değer bitleri içeren bir tamsayı türü kullanır , bu nedenle ayrıntıdaki şeytanı kaçırmak kolaydır.

İşaret bitleri ... Yukarıdaki örnekte UINT_MAX, üst sınır olarak alıntı yaptığımdan unsigned int, değeri 16yorumdan çıkarmak önemsiz bir örnektir . İmzalı türler için, pozitif ve negatif değerleri (bu işarettir) ayırt etmek için işaret bitini de eklememiz gerekir.

INT_MIN                                -32768 // -(2¹⁵)
INT_MAX                                +32767 // 2¹⁵ - 1

Doldurma bitleri ... Tamsayılarda doldurma bitlerine sahip bilgisayarlarla karşılaşmak yaygın olmasa da, C standardı buna izin verir; bazı makineler (yani bu ), iki küçük (işaretli) tamsayı değerini bir araya getirerek daha büyük tamsayı türleri uygular ... ve işaretli tamsayıları birleştirdiğinizde, boşa giden bir işaret biti elde edersiniz. Boşa harcanan bit, C'de dolgu olarak kabul edilir . Diğer dolgu bitlerine örnek olarak parite bitleri ve tuzak bitleri verilebilir .


Gördüğünüz gibi, standart gibi aralıklarını göz önünde bulundurarak teşvik görünüyor INT_MIN.. INT_MAXve diğer asgari / standardından maksimum değerler tamsayı tiplerini seçme ve zorlaştırır, muhtemelen gibi unutulmaya diğer ince faktör bulunmaktadır boyutlarda güvenerek CHAR_BITve dolgu bitleri hangi değerini etkileyebilir sizeof (int)(yani, iki bayt ve dört bayt tamsayıların yaygın yanılgıları bu ayrıntıları ihmal eder).


13

C99 N1256 standart taslak

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

Boyutu intve diğer tüm tamsayı türleri uygulama tanımlıdır, C99 sadece şunları belirtir:

  • minimum boyut garantileri
  • türler arasında göreceli boyutlar

5.2.4.2.1 "Tamsayı tiplerinin <limits.h>boyutları" minimum boyutları verir:

1 [...] Uygulama tanımlı değerleri, gösterilen değerlere eşit veya daha büyük olmalıdır (mutlak değer) [...]

  • UCHAR_MAX 255 // 2 8-1
  • USHRT_MAX 65535 // 2 16-1
  • UINT_MAX 65535 // 2 16-1
  • ULONG_MAX 4294967295 // 2 32-1
  • ULLONG_MAX 18446744073709551615 // 2 64-1

6.2.5 "Türler" diyor ki:

8 Aynı imzaya ve farklı tamsayı dönüştürme derecesine sahip iki tamsayı türü için (bkz. 6.3.1.1), daha küçük tamsayı dönüştürme derecesine sahip türün değer aralığı, diğer türün değerlerinin bir alt aralığıdır.

ve 6.3.1.1 "Boole, karakterler ve tamsayılar" göreli dönüşüm sıralarını belirler:

1 Her tamsayı türünün, aşağıdaki gibi tanımlanmış bir tamsayı dönüştürme sırası vardır:

  • Uzun uzun int sıralaması, uzun int'nin sıralamasından daha büyük olacaktır, bu da int sıralamasından daha büyük olacaktır, bu kısa int'nin sıralamasından daha büyük olacaktır, bu da imzalı karakter sıralamasından daha büyük olacaktır.
  • İmzasız herhangi bir tamsayı türünün sırası, varsa, karşılık gelen işaretli tamsayı türünün sırasına eşit olacaktır.
  • T1, T2 ve T3 tüm tamsayı türleri için, eğer T1 T2'den daha yüksek bir sıraya sahipse ve T2 T3'ten daha yüksek bir sıraya sahipse, T1 T3'ten daha yüksek bir sıraya sahipse

8

Sadece garanti eder olan charolmalıdır en azından geniş 8 bit, shortve intolmalı , en az 16 bit genişliğinde ve longolmalı , en azından geniş 32 bit, ve sizeof (char)<= sizeof (short)<= sizeof (int)<=sizeof (long) (aynı olan türde işaretsiz versiyonları için de geçerlidir ).

int platforma bağlı olarak 16 ila 64 bit genişliğinde olabilir.


6

C boyutu “int” 2 bayt mı yoksa 4 bayt mı?

Cevap "evet" / "hayır" / "belki" / "belki değil" dir.

C programlama dili aşağıdakileri belirtir: "bayt"char olarak bilinen ve "bayt" olarak da adlandırılan en küçük adreslenebilir birim, tam olarak CHAR_BITbit genişliğindedir;CHAR_BIT en az 8'dir.

Yani, C'deki bir bayt mutlaka bir oktet değildir , yani 8 bittir. Geçmişte C kodunu (ve Unix) çalıştıran ilk platformlardan birinde 4 bayt vardı int- ancak toplamda 9 intbit vardı, çünkü 9'du CHAR_BIT!

inten azından-32767 ... 32767 aralığı olan platform için doğal tamsayı boyutu olması gerekiyordu . intPlatform baytlarının boyutunu aşağıdakilerle alabilirsiniz sizeof(int); bu değeri çarptığınızda CHAR_BIT, bit cinsinden ne kadar geniş olduğunu bilirsiniz.


36-bit makineler çoğunlukla ölü olsa da, hala 8-bit bayt olmayan platformlar var. Daha dün 16 bit baytlı bir Texas Instruments MCU hakkında bir soru vardı , C99, C11 uyumlu bir derleyiciye .

On TMS320C28x görülüyor ki char, shortve intvardır her dolayısıyla bir byte 16 bit genişliğinde ve. long int2 bayt ve long long int4 bayttır. C'nin güzelliği, böyle bir platform için hala etkili bir program yazabiliyor ve hatta taşınabilir bir şekilde yapabiliyor!


"çünkü CHAR_BIT 9 yaşındaydı!" - O zamanlar 362880 bit bilgisayar kullanıyorlardı !? Etkileyici.
Josh Desmond

5

Çoğunlukla derleyicilerinde compiler.Nowadays için derleyici bağlıdır Eğer .Bu kullandığınız platforma bağlıdır int taşımaktadır 4 bayt . Derleyicinizin ne kullandığını kontrol etmek istiyorsanız kullanabilirsiniz sizeof(int).

main()
{
    printf("%d",sizeof(int));
    printf("%d",sizeof(short));
    printf("%d",sizeof(long));
}

C derleyici vaat tek şey kısa boyutu int eşit veya daha küçük olması ve uzun boyutu int eşit veya daha fazla olmalıdır. Yani int boyutu 4 ise, o zaman kısa boyutu 2 veya 4 olabilir ama daha büyük değil Aynı şey uzun ve int için de geçerlidir. Ayrıca kısa ve uzun boyutların aynı olamayacağını söylüyor.


1
Kullanılması %dBir için size_tparametre UB olduğunu.
Paul R

3

Bu uygulamaya bağlıdır, ancak genellikle x86 ve ARM intler gibi diğer popüler mimariler 4 bayt alır. Kullanarak her zaman derleme zamanında kontrol edebilirsinizsizeof(int) veya kontrol etmek istediğiniz başka bir türü kontrol edebilirsiniz.

Belirli bir boyutta bir tür kullandığınızdan emin olmak istiyorsanız, <stdint.h>


2
#include <stdio.h>

int main(void) {
    printf("size of int: %d", (int)sizeof(int));
    return 0;
}

Bu 4 değerini döndürür, ancak muhtemelen makineye bağlıdır.


1

C boyutu “int” 2 bayt mı yoksa 4 bayt mı?

C'deki bir Tamsayı değişkeni 2 bayt mı yoksa 4 bayt mı?

C "bayt" ın "bayt" başına 8 bit dışında bir şey olmasına izin verir.

CHAR_BIT bit alanı (bayt) olmayan en küçük nesne için bit sayısı C11dr §5.2.4.2.1 1

8'den büyük bir değerin değeri giderek yaygınlaşmaktadır. Maksimum taşınabilirlik için kullanmak CHAR_BITyerine, Şekil 8, bir boyutu intolarak bit C olan sizeof(int) * CHAR_BIT.

#include <limits.h>
printf("(int) Bit size %zu\n", sizeof(int) * CHAR_BIT);

Bağlı olduğu faktörler nelerdir?

intBit boyutu genel olarak 32 ya da 16 bittir. C belirtilen minimum aralıklar :

int INT_MIN-32767 türündeki bir nesne için minimum değer +32767 C11dr §5.2.4.2.1 1 türündeki
bir nesne için maksimum değerint INT_MAX

Minimum aralık için intkuvvetleri bit boyutu için en az bir işlemci "8-bit" bile - 16. Özel işlemcilerde 64 bit gibi bir boyut görülür. 18, 24, 36 gibi diğer değerler tarihi platformlarda meydana gelmiştir veya en azından teorik olarak mümkündür. Modern kodlama, 2'nin gücü olmayanlar için nadiren endişelenirint bitlik boyutları için .

Bilgisayarın işlemcisi ve mimarisi int bit boyutu seçimini yönlendirir.

Yine de 64 bit işlemcilerde bile, intbüyük kod tabanları int32 bit (veya 32/16) olmasına bağlı olduğu için , derleyici boyutu uyumluluk nedeniyle 32 bit olabilir.


-1

Bu, bu soruyu cevaplamak için iyi bir kaynaktır.

Ama bu soru her zaman "Evet. Her ikisi de" şeklinde bir cevaptır.

Bu, mimarinize bağlıdır. 16 bit veya daha az bir bilgisayarda çalışacaksanız, 4 bayt (= 32 bit) olamaz. 32 bit veya daha iyi bir makinede çalışıyorsanız, uzunluğu 32 bittir.

Anlamak için, programın okunabilir bir şey çıkarmaya hazır olmasını sağlayın ve "sizeof" işlevini kullanın. Bu, beyan edilen veri türünüzün bayt cinsinden boyutunu döndürür. Ancak bunu dizilerle kullanırken dikkatli olun.

Eğer beyan ediyorsanız int t[12];12 * 4 bayt dönecektir. Bu dizinin uzunluğunu elde etmek için kullanın sizeof(t)/sizeof(t[0]). Bir gönderme dizisinin boyutunu hesaplaması gereken bir işlev oluşturacaksanız,

typedef int array[12];
int function(array t){
    int size_of_t = sizeof(t)/sizeof(t[0]);
    return size_of_t;
}
void main(){
    array t = {1,1,1};  //remember: t= [1,1,1,0,...,0]
    int a = function(t);    //remember: sending t is just a pointer and equal to int* t
   print(a);   // output will be 1, since t will be interpreted as an int itselve. 
}

Yani bu farklı bir şey bile getirmeyecek. Bir dizi tanımlar ve daha sonra uzunluğu elde etmeye çalışırsanız sizeof kullanın. Bir işleve bir dizi gönderirseniz, gönderme değerinin yalnızca ilk öğedeki bir işaretçi olduğunu unutmayın. Ancak bir durumda, dizinizin ne kadar büyük olduğunu her zaman bilirsiniz. Durum iki, iki işlevi tanımlayarak çözülebilir ve bazı performansları kaçırır. Fonksiyonu (dizi t) tanımlayın ve fonksiyon2'yi (dizi t, int size_of_t) tanımlayın. Uzunluğunu bazı kopyalama çalışmalarıyla ölçmek için "function (t)" çağırın ve sonucu değişken dizi boyutlarında istediğinizi yapabileceğiniz function2'ye gönderin.


O her zaman doğru olmayan şeyleri kabul eder, çünkü sağlanan bağlantı bilgilerinin kötü kaynağıdır (örneğin chardaima signed)
Andrei Damian-Fekete
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.