Operatörler C'nin fiilleridir: değer alır ve yenilerini üretirler. Yaklaşık 40 tane vardır, ama bir düzinesi kodun çoğunu kapsar ve bunlardan ikisinin kendi bölümlerini hak edecek kadar keskin tuzakları vardır.
Aritmetik Operatörler
(Biçim metnindeki %% gerçek bir yüzde işareti yazdırır - tek başına % bir biçim belirteci başlatırdı.)
Beş ikili aritmetik operatör + - * / %'dir, artı olumsuzlama için tekli - ve esasen hiçbir şey yapmayan +.
Tam Sayı Bölmesi Tuzağı
İki tam sayıyla a / b, tam sayı bölmesi yapar ve kalanı atar. Yuvarlama yoktur - sonuç sıfıra doğru kırpılır.
O son durum ürüne kadar giden hatadır. Bir double'a atamak yardımcı olmaz: total / count bölmesi atama gerçekleşmeden önce çoktan tamamlanmış ve çoktan bir int olmuştur. Çözüm, ifadenin içinde bir işleneni kayan noktalı yapmaktır; genellikle bir dönüşümle.
İki ilgili kural: tam sayılarla sıfıra bölmek tanımsız davranıştır ve tipik olarak programı çökertir; ayrıca INT_MIN / -1 taşar.
Mod Operatörü
% kalanı verir ve yalnızca tam sayılarda çalışır:
Çiftlik için x % 2 == 0 testi ve bir indeksi bir dizi etrafında sarmak için % n kullanmak, iki günlük kullanımdır.
Negatif sayılarla C'nin %'si bölünenin işaretini izler:
Dolayısıyla x negatif olabildiğinde x % 2 == 1 teklik için bozuk bir testtir - -7 % 2 sonucu -1'dir. Bunun yerine x % 2 != 0 kullanın.
Kayan noktalı kalanlar için % bir derleme hatasıdır; math.h'deki fmod()'u kullanın.
Atama ve Bileşik Atama
= bir değer saklar. Bileşik biçimler bir işlemi saklamayla birleştirir:
x += 5, x = x + 5 demektir, ama x'i yalnızca bir kez değerlendirir - hedef arr[compute_index()] gibi bir şey olduğunda bu önemlidir.
Atamanın kendisi, atanan değeri üreten bir ifadedir; a = b = c = 0'ın çalışmasının (sağdan sola atar) ve = ile == hatasının sessizce derlenmesinin sebebi budur.
Artırma ve Azaltma
++ bir ekler, -- bir çıkarır. Her biri ön ek ve son ek biçiminde gelir:
Tek başına bir deyim olarak ikisi birbirinin yerine geçer ve for başlığındaki alışıldık seçim olan i++, gelenekten başka derin bir sebebi olmadan öyledir.
Yapmamanız gereken şey, aynı zamanda değiştirildiği bir ifadede bir değişkeni birden fazla kez kullanmaktır:
int i = 5;
int x = i++ + i++; /* tanımsız davranış */
arr[i] = i++; /* tanımsız davranış */
printf("%d %d", i++, i);/* tanımsız davranış */
C, o alt ifadelerin değerlendirilme sırasını tanımlamaz, dolayısıyla sonuç yalnızca belirtilmemiş değildir - tüm programın davranışı tanımsızdır. Deyimi ikiye bölün, belirsizlik yok olur.
Karşılaştırma Operatörleri
Altı tanedir ve hepsi bir int üretir: doğru için 1, yanlış için 0.
Sonucun ayrılmış bir boolean türü yerine düz bir int olması C'nin tanımlayıcı bir özelliğidir - = ile == hatası dahil bundan çıkanlar için bkz. C'de booleanlar.
İki karşılaştırma hatası C'ye özgüdür. Zincirleme, matematiğin düşündürdüğü gibi çalışmaz: if (1 < x < 10) her zaman doğrudur, çünkü 1 < x 0 ya da 1'e değerlenir ve sonra bu 10 ile karşılaştırılır. if (x > 1 && x < 10) yazın. Ve metinleri == ile karşılaştırmak metni değil göstericileri karşılaştırır - string.h'deki strcmp'yi kullanın.
Mantıksal Operatörler
&& VE'dir, || VEYA'dır, ! DEĞİL'dir. Üçü de sıfırdan farklı her değeri doğru sayar.
Kısa devre yaparlar: && bir işlenen yanlış olur olmaz durur ve || biri doğru olur olmaz durur. Gerisi asla değerlendirilmez ve bu yalnızca bir iyileştirme değildir - güvenlik için güvenebileceğiniz bir garantidir:
O iki testin sırasını değiştirin, NULL çağrısı boş bir göstericiyi dereferans eder ve çöker. Önce koruyun, sonra kullanın - bir && zincirindeki sıra mantığın bir parçasıdır.
Koşul Operatörü
C'nin tek üç işlenenli operatörü iki değer arasından seçer:
kosul ? dogruysa_deger : yanlissa_deger. Bir ifadedir, dolayısıyla bir if deyiminin sığamayacağı yerlere sığar - bir printf argümanının içine, bir ilk değere. Kısa tutun; iç içe koşullar hızla okunmaz hâle gelir.
Kısaca Bit Düzeyi Operatörler
Bunlar bir tam sayının tek tek bitleri üzerinde çalışır:
Bayraklar, maskeler ve donanım yazmaçları için kullanılırlar. İki uyarı: & ve |, && ve || değildir (kısa devre yapmazlar ve bit bit çalışırlar) ve işaretli bir değeri kaydırmak ya da tipin genişliğinden fazla kaydırmak tanımsızdır. Bit işleri için işaretsiz tipler kullanın.
Öncelik
Bir ifadede parantez olmadığında neyin neye bağlanacağına bu tablo karar verir. En yüksek öncelik önce:
| Seviye | Operatörler | Birleşme |
|---|---|---|
| 1 | () [] -> . x++ x-- | önceden sonraya |
| 2 | ! ~ ++x --x +x -x *p &x sizeof (tip) | sondan öne |
| 3 | * / % | önceden sonraya |
| 4 | + - | önceden sonraya |
| 5 | << >> | önceden sonraya |
| 6 | < <= > >= | önceden sonraya |
| 7 | == != | önceden sonraya |
| 8 | & | önceden sonraya |
| 9 | ^ | önceden sonraya |
| 10 | bit düzeyi VEYA | önceden sonraya |
| 11 | && | önceden sonraya |
| 12 | mantıksal VEYA | önceden sonraya |
| 13 | ?: | sondan öne |
| 14 | = += -= *= /= %= ve arkadaşları | sondan öne |
| 15 | , | önceden sonraya |
Pratik sonuçlar:
a + b * c /* a + (b * c) demektir */
a < b == c < d /* (a < b) == (c < d) demektir - nadiren kastedilen şey */
x & 1 == 0 /* x & (1 == 0), yani x & 0 demektir - klasik bir hata */
*p++ /* *(p++) demektir - p'yi dereferans et, sonra ilerlet */
O üçüncü satır ezberlenmeye değer: ==, &'den daha sıkı bağlanır, dolayısıyla bit maskesi testleri parantez ister - (x & 1) == 0.
Kimse on beş seviyenin hepsini hatırlamaz ve kimsenin hatırlamasına gerek yok. *'ın +'yı yendiğini, karşılaştırmaların &&'i, onun da ||'yi yendiğini ve geri kalan her şeyin parantez aldığını öğrenin:
if ((flags & MASK) != 0 && (count > 0 || force)) { ... }
O satırda gereksiz parantezler var ve onlarla daha iyi.
Sıkça Sorulan Sorular
C'de % ne yapar?
% mod operatörüdür: tam sayı bölmesinin kalanını verir. 17 % 5 sonucu 2'dir. Yalnızca tam sayılarda çalışır - onu bir float ya da double üzerinde kullanmak derleme hatasıdır ve math.h'deki fmod() kayan nokta karşılığıdır.
C'de 5 / 2 neden 2 verir?
Çünkü her iki işlenen de tam sayıdır, dolayısıyla C tam sayı bölmesi yapar ve kesri atar. 2.5 almak için bir tarafı kayan noktalı bir değer yapın: 5 / 2.0 ya da bir işleneni (double)a / b ile dönüştürün.
i++ ile ++i arasındaki fark nedir?
İkisi de i'ye bir ekler. ++i (ön ek) önce artırır ve yeni değeri üretir; i++ (son ek) eski değeri üretir ve sonradan artırır. Tek başına bir deyim olarak özdeştirler - fark yalnızca sonuç kullanıldığında önemlidir, int b = a++; ile int b = ++a; gibi.
C'de operatör önceliği nedir?
Bir ifadede parantez olmadığında operatörlerin bağlanma sırasıdır. *, / ve %, + ve -'den daha sıkı bağlanır; onlar da karşılaştırmalardan, karşılaştırmalar &&'den, o da ||'den, o da atamadan daha sıkı bağlanır. Şüphelendiğinizde parantez ekleyin - hiçbir maliyetleri yoktur ve soruyu ortadan kaldırırlar.