Yanıtlar:
size_t
Tipi sonucudur işaretsiz tamsayı türüdür sizeof
operatör (ve offsetof
o sistem işleyebilir büyük nesne (örneğin 8Gb statik dizi) boyutunu içerecek yeterince büyük olması sağlanır, böylece operatör).
size_t
Tip bir daha, daha büyük eşit veya daha küçük olabilir unsigned int
, ve derleyici optimizasyon için bu konuda varsayımları yapabiliriz.
Daha kesin bilgileri, taslağı internette pdf formatında mevcut olan C99 standardı, bölüm 7.17'de veya pdf taslağı olarak da bulunan C11 standardı, kısım 7.19'da bulabilirsiniz .
size_t
! Değilse, kim yapar?
Klasik C (C Programlama Dili, Prentice-Hall, 1978'de Brian Kernighan ve Dennis Ritchie tarafından tanımlanan C'nin ilk lehçesi) yoktu size_t
. size_t
Taşınabilirlik sorununu ortadan kaldırmak için C standartları komitesi
Embedded.com'da ayrıntılı olarak açıklanmıştır (çok iyi bir örnekle)
Kısacası, size_t
asla olumsuz değildir ve performansı en üst düzeye çıkarır çünkü hedef platformda mümkün olan en büyük nesnenin boyutunu temsil etmek için yeterince büyük - ancak çok büyük olmayan - imzasız tam sayı türü olarak tanımlanır.
Boyutlar asla negatif olmamalıdır ve gerçekten size_t
imzasız bir tiptir. Ayrıca, size_t
imzasız olduğu için, işaretli tamsayıdaki diğer tüm bitler gibi, işaret bitini büyüklüğü temsil etmek için kullanabileceğimizden, karşılık gelen işaretli türden kabaca iki kat daha büyük sayıları saklayabilirsiniz. Bir bit daha kazandığımızda, temsil edebileceğimiz sayı aralığını yaklaşık iki kat artarız.
Peki, neden sadece bir unsigned int
? Yeterince büyük sayıları tutamayabilir. unsigned int
32 bitlik bir uygulamada , temsil edebileceği en büyük sayı 4294967295
. IP16L32 gibi bazı işlemciler 4294967295
bayttan daha büyük nesneleri kopyalayabilir .
Peki, neden kullanmıyorsunuz unsigned long int
? Bazı platformlarda bir performans ücretini etkiler. Standart C, long
en az 32 bit işgal etmeyi gerektirir . Bir IP16L32 platformu, her bir 32 bit uzunluğunu bir çift 16 bit kelime olarak uygular. Bu platformlardaki hemen hemen tüm 32 bit operatörler, daha fazla olmasa da iki talimat gerektirir, çünkü iki 16 bitlik parçadaki 32 bit ile çalışırlar. Örneğin, 32 bit uzunluğunu taşımak genellikle iki makine talimatı gerektirir - her biri 16 bitlik yığınları taşımak için bir tane.
Kullanmak size_t
bu performans ücretini önler. Göre bu fantastik makalede , "Tür size_t
tipik bazı işaretsiz tamsayı türü için bir takma ad bir typedef unsigned int
veya unsigned long
ancak hatta unsigned long long
. Ama needed-- daha büyük - Her Standart C uygulaması yeterince büyük olduğunu işaretsiz tamsayı seçmek gerekiyordu hedef platformda mümkün olan en büyük nesnenin boyutunu temsil etmek. "
unsigned int
edilebilecek ve bir sistemden diğerine değişebilen en büyük değer . En azından olması gerekiyor 65536
, ancak bazı sistemlerde yaygın olarak 4294967295
ve 18446744073709551615
(2 ** 64-1) olabilir .
unsigned char
) hakkındaki tüm mutlak garantileri kaldırdığı izlenimi altındayım . Standart hiçbir yerde '65535' veya '65536' dizesini içermiyor gibi görünüyor ve '+32767' yalnızca bir notta temsil edilebilecek en büyük tam sayı olarak (1.9: 9) oluşur int
; INT_MAX
bundan daha küçük olamaz bile garanti verilmez !
Size_t türü, sizeof operatörü tarafından döndürülen türdür. Ana makinede desteklenen herhangi bir bellek aralığının boyutunu bayt cinsinden ifade edebilen işaretsiz bir tam sayıdır. (Tipik olarak), ptrdiff_t öğesinin, sizeof (ptrdiff_t) ve sizeof (size_t) eşit olacak şekilde işaretli bir tam sayı değeri olmasıyla ilgilidir.
C kodu yazarken , bellek aralıkları ile uğraşırken daima size_t kullanmalısınız.
Diğer yandan int türü temel olarak ana makinenin tamsayı aritmetiğini en verimli şekilde gerçekleştirmek için kullanabileceği (işaretli) tamsayı değerinin boyutu olarak tanımlanır. Örneğin, birçok eski PC tipi bilgisayarda sizeof (size_t) değeri 4 (bayt) olur, ancak sizeof (int) 2 (bayt) olur. 16 bit aritmetik 32 bit aritmetikten daha hızlıydı, ancak CPU 4 GiB'ye kadar (mantıksal) bellek alanını işleyebiliyordu.
İnt türünü yalnızca verimliliği önemsediğiniz zaman kullanın çünkü gerçek hassasiyeti hem derleyici seçeneklerine hem de makine mimarisine bağlıdır. Özellikle C standardı aşağıdaki değişmezleri belirtir: sizeof (char) <= sizeof (kısa) <= sizeof (int) <= sizeof (uzun), bu ilkel tipler.
Not: Bu Java ile aynı DEĞİLDİR (aslında 'char', 'byte', 'short', 'int' ve 'long' türlerinin her biri için bit hassasiyetini belirtir).
size_t
herhangi bir nesnenin boyutunu temsil edebilir (örneğin: sayı, dizi, yapı). Tüm bellek aralığı aşılabilirsize_t
size_t
- Umarım bunu demek istemezsiniz. Çoğu zaman, adres alanının + taşınabilirliğinin önemli olduğu dizilerle ilgilenmiyoruz. Bu gibi durumlarda alırsınız size_t
. Diğer her durumda indeksleri (imzalı) tamsayılardan çıkarırsınız. Çünkü imzasızların beklenmedik taşma davranışından kaynaklanan karışıklık (uyarı olmadan gelir), diğer durumlarda ortaya çıkabilecek taşınabilirlik sorunlarından daha yaygın ve daha kötüdür.
Size_t türü, olası herhangi bir nesnenin boyutunu depolayacak kadar büyük olmalıdır. İmzasız int'in bu koşulu yerine getirmesi gerekmez.
Örneğin, 64 bit sistemlerde int ve unsigned int 32 bit genişliğinde olabilir, ancak size_t, 4G'den büyük sayıları depolayacak kadar büyük olmalıdır
size_t
derleyici bir X tipi kabul edebilirse, sizeof (X) 4G'den daha büyük bir değer verir. Çoğu derleyici reddeder typedef unsigned char foo[1000000000000LL][1000000000000LL]
ve foo[65536][65536];
belgelenmiş bir uygulama tanımlı sınırı aşarsa meşru bir şekilde reddedilebilir.
Glibc 0.02 el kitabından alıntı, konuyu araştırırken de geçerli olabilir:
2.4 sürümünden önce GCC'nin size_t türü ve sürümleriyle ilgili potansiyel bir sorun var. ANSI C size_t öğesinin her zaman imzasız bir tip olmasını gerektirir. Mevcut sistemlerin başlık dosyalarıyla uyumluluk için GCC, stddef.h' to be whatever type the system's
sys / types.h dosyasında size_t öğesini tanımlar. Sys / types.h dosyasında size_t öğesini tanımlayan çoğu Unix sistemi, bunu imzalı bir tür olarak tanımlar. Kitaplıktaki bazı kodlar size_t öğesinin imzasız tür olmasına bağlıdır ve imzalanmışsa düzgün çalışmaz.
Size_t öğesinin imzasız olmasını bekleyen GNU C kütüphane kodu doğrudur. Size_t öğesinin işaretli tür olarak tanımı yanlış. 2.4 sürümünde, GCC'nin fixincludes' script will massage the system's
boyut_t değerini her zaman imzasız bir tür olarak ve sys / types.h ' olarak tanımlamasını planlıyoruz.
Bu arada, bu soruna geçici olarak GCC'ye GNU C kütüphanesini derlerken size_t için imzasız bir tür kullanmasını söyleyerek çalışırız. “configure”, GCC'nin size_t için kullandığı türü otomatik olarak algılar ve gerekirse geçersiz kılmayı ayarlar.
Derleyicim 32 bit olarak ayarlanmışsa, size_t
typedef için başka bir şey değildir unsigned int
. Derleyicim 64 bit olarak ayarlanmışsa, size_t
typedef'den başka bir şey değildir unsigned long long
.
unsigned long
Bazı işletim sistemlerinde her iki durum için de tanımlanabilir .
size_t bir işaretçinin boyutudur.
Yani 32 bit veya ortak ILP32 (tamsayı, uzun, işaretçi) model size_t 32 bittir. ve 64 bit veya ortak LP64 (uzun, işaretçi) model boyutu_t 64 bittir (tamsayılar hala 32 bittir).
Başka modeller var ama bunlar g ++ 'ın kullandığı modeller (en azından varsayılan olarak)
size_t
her ne kadar yaygın olarak olsa da, bir işaretçi ile aynı boyutta olması gerekmez. Bir işaretçi bellekteki herhangi bir yeri gösterebilmelidir; size_t
yalnızca en büyük tek nesnenin boyutunu temsil edecek kadar büyük olmalıdır.