1.6.1 if

The if statement evaluates an expression. If that expression is true, then a statement is executed. If an else clause is given and if the expression is false, then the else’s statement is executed.

Syntax:

if( expression ) statement1;

or

if( expression ) statement1;
else statement2 ;

Examples:

if(loop<3) counter++;

if(x==y)
  x++;
else
  y++;

if(z>x)
 {
  z=5;
  x=3;
 }
else
 {
  z=3;
  x=5;
 }

1.6.1 if

The if statement evaluates an expression. If that expression is true, then a statement is executed. If an else clause is given and if the expression is false, then the else’s statement is executed.

Syntax:

if( expression ) statement1;

or

if( expression ) statement1;
else statement2 ;

Examples:

if(loop<3) counter++;

if(x==y)
  x++;
else
  y++;

if(z>x)
 {
  z=5;
  x=3;
 }
else
 {
  z=3;
  x=5;
 }

if DEYİMİ

C dilinde program akışını denetlemeye yönelik en önemli deyim if deyimidir.
En yalın biçimiyle if deyiminin genel sözdizimi aşağıdaki gibidir:

if (ifade)
deyim;

if ayracı içindeki ifadeye koşul ifadesi (conditional expression) denir.
if ayracını izleyen deyime, if deyiminin doğru kısmı (true path) denir.

if deyiminin doğru kısmını oluşturan deyim, bir yalın deyim (simple statement) olabileceği
gibi, bir boş deyim (null statement), bir bileşik deyim (compound statement) ya da
başka bir kontrol deyimi de (control statement) olabilir.

Yalın if deyiminin yürütülmesi aşağıdaki gibi olur:
Önce koşul ifadesinin sayısal değerini hesaplar. Hesaplanan sayısal değer, mantıksal
DOĞRU ya da YANLIŞ olarak yorumlanır. Koşul ifadesinin hesaplanan değeri 0 ise yanlış,
0’dan farklı bir değer ise doğru olarak yorumlanır. Örneğin koşul ifadesinin hesaplanan
değerinin –5 olduğunu düşünelim. Bu durumda kontrol ifadesi doğru olarak
değerlendirilir. Eğer ifade DOĞRU olarak yorumlanırsa, if deyiminin doğru kısmı yapılır,
ifade YANLIŞ olarak yorumlanırsa doğru kısmı yapılmaz. Yalın if deyimi, bir ifadenin
doğruluğuna ya da yanlışlığına göre, bir deyimin yapılması ya da yapılmamasına dayanır.
Aşağıdaki programı derleyerek çalıştırın:

int main()
 {
int x;

printf("bir sayi girin : ");
scanf("%d", &x);

if (x > 10)
printf("if deyiminin doğru kısmı!\n");

return 0;
 }

main işlevi içinde yazılan if deyimiyle, klavyeden girilen tamsayının 10’dan büyük olması
durumunda printf çağrısı yürütülür, aksi halde yürütülmez.

Yanlış Kısmı Olan if Deyimi
if kontrol deyimi, else anahtar sözcüğünü de içerebilir. Böyle if deyimine, yanlış kısmı
olan if deyimi denir. Yanlış kısmı olan if deyiminin genel biçimi aşağıdaki gibidir:

if (ifade)
deyim1;
else
deyim2;

Bu kez if deyiminin doğru kısmını izleyen deyimden sonra else anahtar sözcüğünün, daha
sonra ise bir başka deyimin yer aldığını görüyorsunuz. Genel biçimdeki deyim2’ye if
deyiminin yanlış kısmı (false path) denir.
if deyiminin koşul ifadesi, mantıksal olarak DOĞRU ya da YANLIŞ olarak yorumlanır. Bu
kez koşul ifadesinin DOĞRU olması durumunda deyim1, YANLIŞ olarak yorumlanması
durumunda deyim2 yapılır. Yanlış kısmı olan if deyimi, bir koşul ifadesinin doğru ya da yanlış olmasına göre iki ayrı deyimden birinin yapılmasına yöneliktir. Yani ifade doğru ise

bir iş, yanlış ise başka bir iş yapılır.
Aşağıdaki örneği inceleyin:

#include <stdio.h>

int main()
 {
char ch;

printf("bir karakter girin : ");
ch = getchar();

if (ch >= 'a' && ch <= 'z')
printf("%c kucuk harf!\n", ch);
else
printf("%c kucuk harf degil!\n", ch);

return 0;
 }

Yukarıdaki main işlevinde standart getchar işlevi kullanılarak klavyeden bir karakter alınıyor. Alınan karakterin sıra numarası, ch isimli değişkene atanıyor. Koşul ifadesinin doğru ya da yanlış olması durumuna göre, klavyeden alınan karakterin küçük harf olup
olmadığı bilgisi ekrana yazdırılıyor. Koşul ifadesine bakalım:

ch >= ‘a’ && ch <= ‘z’

Bu ifadenin doğru olması için “mantıksal ve (&&)” işlecinin her iki teriminin de doğru
olması gerekir. Bu da ancak, ch karakterinin küçük harf karakteri olması ile mümkündür.

if deyiminin doğru ve/veya yanlış kısmı bir bileşik deyim olabilir. Bu durumda, koşul
ifadesinin doğru ya da yanlış olmasına göre, birden fazla yalın deyimin yürütülmesi
sağlanabilir. Aşağıdaki örneği inceleyin:

/***/
 if (x > 0) {
y = x * 2 + 3;
z = func(y);
result = z + x;
 }
 else {
y = x * 5 - 2;
z = func(y - 2);
result = z + x - y;
 }
 /***/

Yukarıdaki if deyiminde, x > 0 ifadesinin doğru olup olmasına göre, result değişkeninin değeri farklı işlemlerle hesaplanıyor. if deyiminin hem doğru hem de yanlış kısımlarını bileşik deyimler oluşturuyor.
Bir if deyiminin yanlış kısmı olmak zorunda değildir. Ancak bir if deyimi yalnızca else kısmına sahip olamaz. Bu durumda if deyiminin doğru kısmına boş deyim ya da boş bileşik deyim yerleştirilmelidir:

if (ifade)
;
else
deyim1;

ya da

if (ifade)
{ }
else
deyim1;

Yalnızca yanlış kısmı olan, doğru kısmı bir boş deyim olan bir if deyimi, okunabilirlik açısından iyi bir seçenek değildir. Böyle durumlarda daha iyi bir teknik, koşul ifadesinin mantıksal tersini alıp, if deyiminin yanlış kısmını ortadan kaldırmaktır:

if (!ifade)
deyim1;

Aşağıdaki kod parçasını inceleyin:

/***/
if (x > 5)
;
else {
func1(x);
func2(x);
}
/***/

Yukarıdaki if deyiminde, x değişkeninin değeri 5’ten büyükse bir şey yapılmıyor, aksi halde func1 ve func2 işlevleri x değişkeninin değeri ile çağrılıyor. Koşul ifadesi ters çevrilerek if deyimi yeniden yazılırsa:

/***/
if (x <= 5) {
func1(x);
func2(x);
}
/***/

if ayracının içinde, ifade tanımına uygun herhangi bir ifade bulunabilir:

if (10)
deyim1;

if (-1)
deyim2;

Yukarıdaki koşul ifadelerinin değeri, her zaman doğru olarak yorumlanır. Çünkü ifadeler, sıfırdan farklı değere sahiptir.

Aşağıdaki koşul ifadesi ise her zaman yanlış olarak yorumlanacağından if deyiminin doğru kısmı hiçbir zaman yürütülmez:

if (0)
deyim1;

Aşağıdaki if deyiminde ise, x değişkeninin değerinin 0 olup olmamasına göre, deyim1 ve deyim2 yürütülür:

if (x) {
deyim1;
deyim2;
/***/
}

Yukarıdaki yapıyla aşağıdaki yapı eşdeğerdir:

if (x != 0) {
deyim1;
deyim2;
}

Aşağıdaki örneği inceleyin :

if (!x) {
deyim1;
deyim2;
}

Bu if deyiminde ise ancak x değişkeninin değerinin 0 olması durumunda deyim1 ve deyim2 yürütülür. Yine yukarıdaki yapıyla aşağıdaki yapı eşdeğerdir:

if (x == 0) {
deyim1;
deyim2;
}

Koşul İfadesinde Atama İşlecinin Kullanılması if deyiminin koşul ifadesinde atama işleci sıklıkla kullanılır. Böylece, atama işlecinin
ürettiği değerden faydalanılır: Aşağıdaki kod parçasını inceleyin:

if ((x = getval()) > 5)
func1(x);
else
func2(x);

if deyiminin koşul ifadesinde ise, çağrılan getval işlevinin geri dönüş değeri, x değişkenine aktarılıyor. Atama işlecinin ürettiği değerin nesneye atanan değer olduğunu anımsayın. Atama işleci ile oluşturulan ifadenin, öncelik ayracı içine alındığını görüyorsunuz. Bu
durumda hem getval işlevinin geri dönüş değeri x değişkenine aktarılıyor hem de işlevin geri dönüş değerinin 5’ten büyük olup olmadığı sorgulanıyor. Öncelik ayracı kullanılmasaydı getval işlevinin geri dönüş değerinin 5’ten büyük olup olmamasına göre x değişkenine 0 ya da 1 değeri atanırdı. Bu durumda da ya func1 işlevi 1 değeriyle ya da func2 işlevi 0 değeriyle çağrılırdı. Deyim aşağıdaki gibi de yazılabilirdi, değil mi?

x = getval();
if (x > 5)
func1(x);
else
func2(x);

Ancak kalıp kod, daha karmaşık deyimlerin yazılmasında kolaylık sağlar. Aşağıdaki if deyiminin nasıl yürütüleceğini düşünün. “Mantıksal ve” işlecinin birinci kısmının, daha önce ele alınmasının, yani “kısa devre” davranışının güvence altında olduğunu anımsayın.

if ((y = getval()) > 5 && isprime(x))
func1(y);
func2(y);

İç İçe if Deyimleri
if deyiminin doğru ya da yanlış kısmını, başka bir if deyimi de oluşturabilir:

if (ifade1)
if (ifade2) {
deyim1;
deyim2;
deyim3;
}
deyim4;

Bu örnekte ikinci if deyimi birinci if deyiminin doğru kısmını oluşturur. Birinci ve ikinci if deyimlerinin yanlış kısımları yoktur.
İç içe if deyimlerinde, son if anahtar sözcüğünden sonra gelen else anahtar sözcüğü, en içteki if deyimine ait olur:

if (ifade1)
if (ifade2)
deyim1;
else
deyim2;

Yukarıdaki örnekte, yazım biçimi nedeniyle else kısmının birinci if deyimine ait olması gerektiği gibi bir görüntü verilmiş olsa da, else kısmı ikinci if deyimine aittir. else anahtar sözcüğü, bu gibi durumlarda, kendisine yakın olan if deyimine ait olur (dangling else).
else anahtar sözcüğünün birinci if deyimine ait olması isteniyorsa, birinci if deyiminin doğru kısmı bloklanmalıdır:

if (ifade1) {
if (ifade2)
deyim1;
}
else
deyim2;

Yukarıdaki örnekte else kısmı birinci if deyimine aittir.

if (ifade1) {
if (ifade2)
deyim1;
else {
deyim2;
deyim3;
}
deyim4;
}
else
deyim5;

Yukarıdaki örnekte birinci if deyiminin doğru kısmı, birden fazla deyimden oluştuğu için – bu deyimlerden birisi de yine başka bir if deyimidir- bloklama yapılıyor. deyim5, birinci if deyiminin yanlış kısmını oluşturur.

else if Merdiveni
Aşağıdaki if deyimlerini inceleyin:
Eğer bir karşılaştırmanın doğru olarak sonuçlanması durumunda yapılan diğer karşılaştırmaların doğru olması söz konusu değilse, bu tür karşılaştırmalara ayrık karşılaştırma denir. Ayrık karşılaştırmalarda, if deyimlerinin ayrı ayrı kullanılması kötü
tekniktir:

if (m == 1)
printf(“Ocak\n”);
if (m == 2)
printf(Şubat\n”);
if (m == 3)
printf(“Mart\n”);
/***/
if (m == 12)
printf(“Aralık\n”);

Yukarıdaki örnekte m değişkeninin değerinin 1 olduğunu düşünün. Bu durumda ekrana Ocak yazısı yazdırılır. Fakat daha sonra yer alan if deyimleriyle m değişkeninin sırasıyla 2, 3, … 12’ye eşit olup olmadığı ayrı ayrı sınanır. Ama x değişkeni 1 değerine sahip olduğundan, bütün diğer if deyimleri içindeki kontrol ifadelerinin yanlış olarak değerlendirileceği bellidir. Bu durumda birinci if deyiminden sonraki bütün if deyimleri gereksiz yere yürütülmüş olur. Aynı zamanda kodun okunabilirliği de bozulur.

Ayrık karşılaştırmalarda else if merdivenleri kullanılmalıdır:

if (ifade1)
deyim1;
else
if (ifade2)
deyim2;
else
if (ifade3)
deyim3;
else
if (ifade4)
deyim4;
else
deyim5;

Bu yapıda, herhangi bir if deyiminin koşul ifadesi doğru olarak değerlendirilirse programın akışı hiçbir zaman başka bir if deyimine gelmez. Bu yapıya, else if merdiveni (cascaded if / else if ladder) denir. else if merdivenlerinin yukarıdaki biçimde yazılışı, özellikle uzun else if merdivenlerinde okunabilirliği bozduğu için aşağıdaki yazım biçimi, okunabilirlik açısından tercih edilmelidir:

if (ifade1)
deyim1;
else if (ifade2)
deyim2;
else if (ifade3)
deyim3;
else if (ifade4)
deyim4;
else
deyim5;

Merdiveninin en sonundaki if deyiminin yanlış kısmının özel bir önemi vardır. Yukarıdaki örnekte deyim5, merdivenin son if deyiminin else kısmında yer alıyor. Merdiven içindeki hiçbir if deyiminin koşul ifadesi doğru değilse, son if deyimininin yanlış kısmı yapılır, değil mi? Yukarıdaki merdivenin yürütülmesi sonucu, deyim1, deyim2, deyim3, deyim4, deyim5’den biri mutlaka yapılır. Son basamaktaki if deyiminin yanlış kısmı olmayan bir else if merdiveninden, hiçbir iş
yapılmadan da çıkılabilir.
Hem okunabilirlik açısından hem de verim açısından, else if merdiveninde olasılığı ya da sıklığı daha yüksek olan koşullar, daha yukarıya kaydırılmalıdır.

Sık Yapılan Hatalar
Özellikle C’ye yeni başlayanların sık yaptığı bir hata, yalın if deyimiyle yanlış kısmı olan if deyimini birbirine karıştırmaktır. Yani if deyiminin yanlış kısmı unutulur:

#include <stdio.h>

int main()
 {
int x;

printf("bir sayi girin: ");
scanf("%d", &x);

if (x % 2 == 0)
printf("%d cift sayi!\n", x);
printf("%d teksayi!\n", x);

return 0;
 }

if ayracı içindeki ifadenin yanlış olması durumunda bir yanlışlık söz konusu değildir. Ama ifade doğru ise ekrana ne yazılır? Klavyeden 28 değerinin girildiğini düşünelim:

28 çift sayi!
28 tek sayi!

Belki de en sık yapılan hata, if ayracının sonuna yanlışlıkla sonlandırıcı atomun (;) yerleştirilmesidir. Aşağıdaki main işlevini inceleyin:

#include <stdio.h>

int main()
 {
int x;

printf("bir sayi girin: ");
scanf("%d", &x);

if (x % 2 == 0);
printf("%d cift sayi!\n", x);

return 0;
 }

Yukarıdaki main işlevinde, x % 2 == 0 ifadesi doğru da olsa yanlış da olsa printf işlevi çağrılır. printf çağrısı if deyiminin dışındadır. if deyiminin doğru kısmını bir boş deyimin (null statement) oluşturması sözdizim kurallarına kesinlikle uyan bir durumdur. Yazılan if
deyimi, gerçekte “x çift ise bir şey yapma” anlamına gelir. Bilinçli bir biçimde yazılma olasılığı yüksek olmayan bu durum için, derleyicilerin çoğu mantıksal bir uyarı iletisi vermez.

Aynı hata, yanlış kısmı olan bir if deyiminin doğru kısmında yapılsaydı bir sözdizim hatası oluşurdu, değil mi?

if (x > 5);
printf(“doğru!\n”);
else
printf(“yanlış\n”);

else anahtar sözcüğünün, bir if deyimine bağlı olarak kullanılması gerektiğini biliyorsunuz.
Yukarıdaki kod parçasındaki if deyimi, doğru kısmı “hiçbir şey yapma” anlamına gelen bir if deyimidir. Dolayısıyla, else anahtar sözcüğü hiçbir if deyimine bağlanmamış olur. Bu da bir sözdizim hatasıdır. Çünkü bir if deyimine bağlanmayan, bir else olamaz.

Tabi ki bir if deyiminin doğru ya da yanlış kısmını bir boş deyim (null statement) oluşturabilir. Bu durumda okunabilirlik açısından, bu boş deyimin bir tab içeriden yazılması, boş deyimin bilinçli olarak yerleştirildiği konusunda güçlü bir izlenim verir.

if ((val = getval()) != 0)
;

Sık yapılan başka bir yanlışlık, if ayracı içinde karşılaştırma işleci (==) yerine atama işlecinin (=) kullanılmasıdır.

/***/
if (x == 5)
printf(“eşit\n”);
/***/

Yukarıdaki if deyiminde, x değişkeninin değeri 5’e eşitse printf işlevi çağrılıyor.
Karşılaştırma işlecinin yan etkisi yoktur. Yani yukarıdaki if ayracı içinde x değişkeninin değeri, 5 değişmezi ile yalnızca karşılaştırılıyor, değiştirilmiyor. Oysa karşılaştırma işlecinin yerine yanlışlıkla atama işleci kullanılırsa:

/***/
if (x = 5)
printf(“eşit\n”);
/***/

Atama işleci, atama işlecinin sağ tarafındaki ifadenin değerini üretir, if ayracı içindeki ifadenin değeri 5 olarak hesaplanır. 5, sıfır dışı bir değer olduğundan, x değişkeninin değeri ne olursa olsun, printf işlevi çağrılır. Atama işlecinin yan etkisi olduğundan, x değişkenine de if deyiminin yürütülmesi ile 5 değeri atanır.
C derleyicilerinin çoğu, if ayracı içindeki ifade yalın bir atama ifadesi ise, durumu şüpheyle karşılayarak, mantıksal bir uyarı iletisi verir. Örneğin Borland derleyicilerinde tipik bir uyarı iletisi aşağıdaki gibidir:

warning : possibly incorrect assignment! (muhtemelen yanlış atama!)

Oysa if ayracı içinde atama işleci bilinçli olarak da kullanılabilir:

if (x = func())
m = 20;

Bilinçli kullanımda, derleyicinin mantıksal uyarı iletisinin kaldırılması için, ifade aşağıdaki gibi düzenlenebilir:

if ((x = func()) != 0)
m = 20;

Yukarıdaki örnekte olduğu gibi, atama işlecinin ürettiği değer, açık olarak bir karşılaştırma işlecine terim yapılırsa, derleyiciler bu durumda bir “mantıksal uyarı” iletisi vermez.
Çok yapılan başka bir hata da, if deyiminin doğru ya da yanlış kısmını bloklamayı unutmaktır. Yani bir bileşik deyim yerine yanlışlıkla yalın deyim yazılır.

if (x == 10)
m = 12;
k = 15;

Yukarıdaki if deyiminde yalnızca

m = 12;

deyimi if deyiminin doğru kısmını oluşturur.

k = 15;

deyimi, if deyimi dışındadır. Bu durum genellikle programcının, if deyiminin doğru ya da yanlış kısmını önce yalın bir deyimle oluşturmasından sonra, doğru ya da yanlış kısma ikinci bir yalın deyimi eklerken, bloklamayı unutması yüzünden oluşur.
Kodun yazılış biçiminden de, if deyiminin doğru kısmının, yanlışlıkla bloklanmadığı anlaşılıyor. Doğrusu aşağıdaki gibi olmalıydı:

if (x == 10) {
m = 12;
k = 15;
}

Aşağıdaki if deyimi ise, yine if anahtar sözcüğü ile eşlenmeyen bir else anahtar sözcüğü kullanıldığı için geçersizdir:

if ( x == 10)
m = 12;
k = 15;
else /* Geçersiz */
y = 20;

Bu tür yanlışlıklardan sakınmak için bazı programcılar, if deyiminin doğru ya da yanlış kısmı yalın deyimden oluşsa da, bu basit deyimi bileşik deyim olarak yazarlar:

if (x > 10) {
y = 12;
}
else {
k = 5;
}

Yukarıdaki örnekte if deyiminin doğru ya da yanlış kısmına başka bir yalın deyimin eklenmesi durumunda sözdizim hatası ya da bir yanlışlık oluşmaz. Ancak gereksiz bloklamadan kaçınmak okunabilirlik açısından daha doğrudur.

if ayracı içinde, bir değerin belirli bir aralıkta olup olmadığının sınanmak istendiğini düşünün:

if (10 < x < 20)
func();

Yukarıdaki if deyiminde, x değişkeni 10 – 20 değerleri arasında ise func işlevinin çağrılması istenmiş. Ancak if ayracı içinde yer alan ifade her zaman doğrudur. Yani func işlevi çağrısı her zaman yürütülür. Küçüktür işleci soldan sağa öncelik yönüne sahip olduğu için, önce daha soldaki küçüktür işleci değer üretir. İşlecin ürettiği değerin 1 ya da 0 olduğunu biliyorsunuz. Üretilen 1 ya da 0 değeri, daha sağdaki küçüktür işlecinin terimi olur. 20 değeri, 1 ya da 0’dan daha büyük olduğuna göre, ifade her zaman doğrudur.
Tehlikeli bir başka yanlışlık da, if ayracı içindeki ifadenin bir işlev çağrı ifadesi olması durumunda, işlev çağrı işlecinin unutulmasıdır:

if (func())
m = 12;

yerine

if (func)
m = 12;

yazıldığını düşünün. Bu durum bir sözdizim hatası oluşturmaz. Bu durumda her zaman, if deyiminin doğru kısmı yürütülür. C dilinde bir işlev ismi, o işlevin kodunun bellekteki yerine eşdeğer bir adres bilgisi olarak ele alınır. Bu adres bilgisi her zaman sıfırdan farklı bir değer olduğundan, koşul ifadesi her zaman doğru olarak değerlendirilir.