C'deki her değişkenin, onu bildirdiğinizde seçilen ve ömrü boyunca sabit kalan bir tipi vardır. Tip üç şeye karar verir: değişkenin kaç bayt kapladığına, o baytların nasıl yorumlanacağına ve onun üzerinde hangi işlemlerin anlamlı olduğuna.
C'nin tip listesi kısadır. Karmaşıklık değiştiricilerdedir.
Dört Temel Tip
charbir bayt tutar. Tek karakterler ('A'), bir metnin baytları ve bazen minik bir tam sayı olarak kullanılır.intişçi atı tam sayı tipidir. Döngü sayaçları, boyutlar, kimlikler.floatvedoublegerçel sayıları tutar.double'ın hassasiyeti kabaca iki katıdır.voidbir anlamda dördüncü tiptir, ama "değer yok" anlamına gelir -voidbir değişken bildiremezsiniz; yalnızca fonksiyon dönüş tipi, boş parametre listesi ya da tipsiz gösterici olarak kullanabilirsiniz.
3.14f'teki f sonekine dikkat edin. Onsuz sabit bir double'dır ve onu bir float'a atamak hassasiyeti sessizce kaybeder. Bazı derleyiciler bunun için uyarır.
Değiştiriciler: short, long, unsigned
Temel tam sayı tipleri, boyutu ya da işareti değiştiren değiştiricilerle gelir.
Her tam sayı tipinin kendi biçim belirtecine ihtiyacı vardır: short için %hd, int için %d, long için %ld, long long için %lld, unsigned için %u. Yanlışını kullanmak bir yuvarlama hatası değil, tanımsız davranıştır.
unsigned işaret bitini kaldırır ve pozitif aralığı ikiye katlar. Bir unsigned int, -2,1 ile +2,1 milyar yerine 0 ile yaklaşık 4,3 milyar arasını tutar. Gerçekten negatif olamayacak şeyler için doğru seçimdir - boyutlar, bayt sayıları, bit örüntüleri - ve sıfırın altına çıkarılabilecek her şey için bir tuzaktır.
signed; int, short, long ve long long için varsayılandır, dolayısıyla neredeyse hiç yazmazsınız. Önemli olduğu tek yer char'dır: düz char'ın işaretli mi işaretsiz mi olduğu gerçekleştirime bağlıdır, o yüzden işaret önemliyse signed char ya da unsigned char yazın.
Boyutlar: Gerçekte Ne Elde Edersiniz
C standardı kesin boyutları değil asgari değerleri belirtir. Modern 64 bitlik herhangi bir Linux, macOS ya da Windows makinesinde şunu görürsünüz:
| Tip | Tipik boyut | Tipik aralık |
|---|---|---|
char | 1 bayt | -128 ile 127 (ya da 0 ile 255) |
short | 2 bayt | -32.768 ile 32.767 |
int | 4 bayt | -2.147.483.648 ile 2.147.483.647 |
long | 8 bayt (Windows'ta 4) | kabaca ±9,2 kentilyon |
long long | 8 bayt | kabaca ±9,2 kentilyon |
float | 4 bayt | ~7 anlamlı basamak |
double | 8 bayt | ~15 anlamlı basamak |
long double | 16 bayt (değişir) | double'dan fazla |
long satırı insanları yakalayanıdır: Linux ve macOS'ta 8 bayt, 64 bitlik Windows'ta 4 bayttır. long'un 64 bitlik bir değer tutabileceğini varsayan kod taşınabilir değildir. Boyut gereksinimin bir parçasıysa long long ya da stdint.h'deki kesin genişlikli tipleri (int32_t, uint64_t) kullanın.
sizeof: Derleyiciye Sorun
Bir boyutu asla tahmin etmeyin - ölçün:
sizeof bir fonksiyon değil, bir operatördür ve derleme zamanında değerlendirilir. Değeri %zu ile yazdırılan size_t tipindedir.
sizeof(char)'ın tam olarak 1 olması garantidir - C'de bir baytın tanımı budur. Diğer her şey ona göre ölçülür.
limits.h ve float.h
Derleyiciniz için kesin aralıklar adlandırılmış sabitler olarak mevcuttur:
Bir işlemin taşıp taşmayacağını bilmeniz gerektiğinde karşılaştıracağınız değerler bunlardır. a + b'yi hesaplamadan önce if (a > INT_MAX - b) kontrolü, taşmayı olmadan önce saptama yolunuzdur - ki bu önemlidir, çünkü işaretli taşmayı sonradan saptayamazsınız.
Tam Sayı Taşması
Bir değer tipinin aralığını aştığında ne olacağı tamamen işarete bağlıdır.
İşaretsiz taşma tanımlıdır: değer 2^N'e göre sarar.
O ikinci durum gerçek bir hata kaynağıdır. for (unsigned i = n - 1; i >= 0; i--) gibi bir döngü asla bitmez, çünkü işaretsiz bir değer her zaman >= 0'dır.
İşaretli taşma tanımsız davranıştır. "Sarar" değil - tanımsız. Derleyicinin bunun asla olmadığını varsayıp buna göre iyileştirme yapmasına izin verilir; bu da sonradan yazılmış bir taşma denetiminin silinebileceği anlamına gelir:
int sum = a + b;
if (sum < a) { /* derleyici bunu tamamen kaldırabilir */ }
Sınırları kullanarak önceden kontrol edin:
if (b > 0 && a > INT_MAX - b) {
/* a + b taşardı - ele alın */
}
Kayan Nokta Hassasiyeti
float ve double sayıları ikili olarak saklar ve çoğu ondalık kesrin tam bir ikili biçimi yoktur - 1/3'ün tam bir ondalık biçiminin olmadığı gibi.
Bundan çıkan kural: kayan noktalı değerleri asla == ile karşılaştırmayın. Bunun yerine mutlak farkı küçük bir toleransla karşılaştırın.
Ve para için asla kayan nokta kullanmayın. Kuruşları tam sayı olarak saklayın; kuruş cinsinden bir long long, dolar cinsinden bir double'ın olmadığı şekilde kesindir.
Bir Tip Seçmek
Kodun çoğunu kapsayan kısa bir karar listesi:
- Tam sayılar: bir sebebiniz yoksa
int. CPU'nun en verimli şekilde işlediği ve tüm aritmetik kuralların etrafında kurulduğu tiptir. - 2 milyardan büyük her şey:
long longya dastdint.h'dekiint64_t. - Boyutlar, uzunluklar,
sizeofya dastrlen'den gelen dizi indeksleri:size_t. İşaretsizdir ve her nesne için yeterince büyük olması garantidir. - Ondalıklar:
double.float'ı yalnızca büyük dizilerde belleği yarıya indirmek ya da çift duyarlık birimi olmayan gömülü donanımda kullanın. - Tek karakterler ve ham baytlar: metin için
char, ikili veri içinunsigned char. - Doğru/yanlış:
stdbool.h'dekibool- bkz. C'de booleanlar. - Kesin bit genişlikleri (dosya biçimleri, ağ protokolleri, donanım yazmaçları):
stdint.h-uint8_t,int16_t,uint32_tvb.
Tipleri Karıştırmak
Tek bir ifadede iki farklı tipi birleştirdiğinizde C, aritmetiği yapmadan önce onları arkanızdan dönüştürür. Bu genellikle yardımcıdır ve zaman zaman felakettir:
Birincisi tam sayı bölmesidir: her iki işlenen de int'tir, dolayısıyla sonuç bir int'tir ve kesir atılır. Üçüncüsü daha kötüdür - işaretli bir değeri işaretsiz biriyle karşılaştırmak işaretliyi işaretsize dönüştürür ve -1'i devasa bir pozitif sayıya çevirir.
Bu dönüşüm kuralları ve onları açık dönüşümlerle nasıl denetleyeceğiniz, C'de tür dönüşümü sayfasının konusudur.
Sıkça Sorulan Sorular
C'deki temel veri tipleri nelerdir?
Dört temel tip: tek karakterler ve baytlar için char, tam sayılar için int, ondalıklar için float ve double. Değiştiriciler boyutlarını ve işaretlerini değiştirir - short, long, long long, signed ve unsigned - böylece tüm küme oluşur.
C'de bir int kaç bayttır?
Modern masaüstü ve sunucu sistemlerinde neredeyse her zaman 4 bayt (32 bit); bu yaklaşık -2,1 milyar ile 2,1 milyar aralığı verir. Standart yalnızca en az 2 bayt garanti eder ve 16 bitlik mikrodenetleyiciler gerçekten 2 kullanır. Kesin bilmeniz gerekiyorsa sizeof(int) kullanın.
C'de float ile double arasındaki fark nedir?
float 4 bayttır ve yaklaşık 7 anlamlı ondalık basamağa sahiptir; double 8 bayttır ve yaklaşık 15'e. Double, kayan noktalı sabitler ve matematik fonksiyonları için varsayılandır ve milyonlarca değer saklamıyor ya da gömülü bir yonga hedeflemiyorsanız doğru seçim double'dır.
C'de bir int taştığında ne olur?
İşaretli bir int için taşma tanımsız davranıştır - derleyici sarabilir, doyurabilir ya da denetimi tamamen kaldırabilir. İşaretsiz bir int için tamamen tanımlıdır: değer 2^N'e göre sarar, dolayısıyla UINT_MAX + 1 sonucu 0'dır. Asla işaretli taşmaya güvenmeyin.