Amiga C

8. Bölüm

Erdem Taylan

Geçen sayıda belirttiğim gibi, artık yazı dizimizin birinci bölümü olan C diline girişi bitirdik. Bu sayıdan başlayarak C dilini daha derin olarak inceleyeceğiz. Bu aşamada da C dilinin referans kitabı olan "The C Programming Language"'e paralel olarak gideceğiz. Gelecek sayılardaki konu sıramız şöyle olacak:
1) Veri tipleri, operatörler ve ifadeler
2) Program akış kontrolü
3) Fonksiyonlar
4) Pointer ve Diziler (İng. Array)
5) Structure'lar
6) Giriş ve Çıkış

C dilini iyice tanıdıktan sonra, Amiga ile C uygulamalarını inceleyeceğiz.

Yazı dizimizin ikinci bölümünün birinci bölüme göre hızlı olacağını belirtmeliyim. Çünkü bence asıl önemli olan, dile yapılan başlangıcın iyi olmasıydı; dolayısıyla bu bölümün daha uzun ve yavaş işlenmesi gerekliydi. O zaman bundan sonra size biraz daha fazla iş düşüyor.

Şimdi veri tipleri, operatörler ve ifadelerden bağlayarak C'nin temellerini görelim.

DEĞİŞKEN İSİMLERİ:

Değişken isimleri başlangıç karakteri harf olmak şartıyla, harf ve rakamlardan oluşur. "-" karakteri, harf sayılır ve uzun değişken adlarının okunabilirliğini oldukça arttırır. Büyük ve küçük harfler, farklı karakterler olarak değerlendirilirler. Değişkenlerin sadece ilk 8 karakteri değerlendirmeye alınsa da, daha uzun isimler kullanılabilir. Ayrıca C dilinde kullanılan komutlar, değişken adı olarak kullanılamaz. Geleneksel olarak değişkenler küçük harfle, sabit sayılar büyük harfle yazılır.

VERİ TÜRLERİ:

C dilinde birkaç veri türü vardır. Bunlar:

char    Tek byte'lık makinanın karakter setinden bir karakteri depolayabilen veri türü
int     bir tamsayı
floal   tek duyarlıklı virgüllü sayılar
double  çift duyarlıklı virgüllü sayılar
Ayrıca int veri türlerinin başına getirildiğinde değişik sonuçlar veren short ve long büyüklükleri farklı tamsayıları belirtirken, unsigned sadece pozitif pozitif tam sayıları belirtir. Amiga'da bu değişkenlerin uzunlukları byte olarak şöyledir:
short int      2 byte 
long int       4 byte 
unsigned int   2 byte 
int            2 byte 
char           1 byte 
float, double  4 byte
Tamsayı tanımlamaları ekleri int önüne getirilerek yapılabilir. Örneğin,
short int x; 
long int y;

SABİTLER:

Tamsayı (İng. integer) ve float (Tk. virgüllü sayı) sayı sabitlerinin nasıl yazıldığını daha önce görmüştük (x=5; veya x=5.0; gibi). Aynca float sayılar için:

0.12E3
gibi 0.12 çarpı 10 üzeri 3 anlamına gelen bilimsel notasyon da vardır.

Long sabitler, sabitin sonuna "L" eklenerek belirtilir. Örneğin:

x=123L;
gibi.

Ayrıca sekizlik düzendeki sayılar için (İng. octal), sayının başına 0x konularak tanımlanabilir. Örneğin 31 sayısı sekizlik düzende 037. onaltılık düzende ise 0x1f şeklinde yazılır. Bu değişkenlerin sonuna L harfi koyarak onları long yapmak da mümkündür.

Bir karakter sabiti, tek tırnak içine yazılan bir karakterden oluşur. Örneğin, 'e' gibi. Bir karakter sabitinin değeri, o karakterin, karakter sabitindeki değerine eşittir. Örneğin '0' sabiti, ASCII setinde 48'e karşılık gelir. Programda 48 yerine '0' yazmak, programın makinadan makinaya değişebilecek 48 sayısından etkilenmemesini sağlar.

Bir string sabiti ise, sıfır veya daha fazla karakterin çift tırnak içinde yazılması ile tanımlanır. Örneğin, "Amiga Dünyası" veya "" "boş karakter" gibi. Çift karakterler string'e dahil edilmezler.

Teknik olarak bir string sonunda 0 karakteri olan bir karakter dizisidir. Dolayısıyla yukarıdaki string için gerekli olan bellek alanı 13+1 karakter, yani 14 byte'dır.

Burada dikkat edilmesi gereken konu, 'x' ile "x"'in tamamen farklı olmasıdır. İlki bir sayıyı belirtirken, ikincisi bir karakter dizisini belirtir.

TANIMLAMALAR (DEKLERASYONLAR):

Bütün değişkenler kullanılmadan önce tanımlanmalıdır. Bir tanımlama, bir veri türü ve onu izleyen bir veya daha çok değişken adından oluşur. Örneğin:

int lower,x Amiga; 
char c,line[1000];
gibi. Yukarıdaki tanımlamalar;
int lower;
int x;
int Amiga;
char c;
char line[1000];
şeklinde de yapılabilir. Değişkenler tanımlamaları sırasında eşleme işlemine de girebilirler. Örneğin;
char e='e';
int i=0;
float deneme=1.0e-5;

ARİTMETİK OPERATÖRLER:

C dili +, -, *, / ve kalan işlemini yapan % modülü operatörünü destekler. Sonuncusuna bir örnek vermek gerekirse: 25 % 3 = 1'dir.

Parantez kullanılmadığında önce *, / ve % işlemleri, daha sonra +, - işlemleri yapılır. Bütün bu aritmetik işlemler, soldan sağa doğru uygulanır.

KARŞILAŞTIRMA OPERATÖRLERİ:

>, >=, <, <= işaretlerinden oluşur ve bunların hepsi aynı işlem önceliğine sahiptir. Bunların işlem öncelik sırasının bir altında ise eşitlik operatörleri olan,

== !=
operatörleri bulunmaktadır. Karşılaştırma operatörleri işlem önceliği bakımından aritmetik operatörlerin altında bulunur. Dolayısıyla: i<lim-1 demek, tahmin edildiği gibi i<(lim-1) anlamına gelir.

C dilindeki mantıksal operatörler olan && (İng. AND, Tk. VE) ve || (İng. OR, Tk. VEYA) operatörleri, belki de en ilginç operatörlerdir. && ve || operatörleri ile birbirine bağlanan ifadeler, soldan sağa doğru değerlendirilir ve sonucun doğru ya da yanlış olduğu bilinir bilinmez işlem sona erer. Örneğin:

for(i=0;i=lim-1&&(c=getchar())!='\n'&&c!=EOF;++i)
	s[i]=c;
satırında yeni bir karakter okumadan önce s dizisinde yer olup olmadığının kontrol edilmesi gerekir. Çünkü önce karakter alınıp daha sonra yer kalıp kalmadığı kontrol edilirse, yer kalmadığı halde boşuna karakter alınmış olur. Bu da fazla işlem yapılmasına sebep olur. Ayrıca, karakterin EOF'a eşit olup olmadığı karakter alındıktan sonra yapılmalıdır. Sonuç olarak: "VE" (&&) ve "VEYA" (||) operatörleri kullanılırken ifadelerin yazılış sırası program hızını ve çalışmasını etkileyebilir.

Bu operatörlerden başka, 0'dan farklı herhangi bir sayıyı 0'a, 0'ı ise 1'e çeviren bir operatör olan ! (İng. Unary negation) operatörü de bulunmaktadır.

Ünlem operatörü, daha çok aşağıdaki gibi kullanılır:

if(değişken==0); 
ifadesi genellikle,
if(!değişken);
biçiminde yazılır.

TÜR DEĞİŞTİRMELER:

Eğer ifadelerde birbirinden farklı türlerde değişkenler birarada kullanılıyorsa, değişkenlerin hepsi ortak bir veri türüne çevrilir. Çevrilme işlemini belirleyen birkaç kural vardır:

Birinci olarak char (Tk. karakter) ve int'ler (Tk. tamsayı), ifadelerde serbestçe karıştırılabilirler: Bütün karakterler aritmetik işlemlerde tamsayılara çevrilir. Bu durum, karakterler ile ilgili işlemlerin esnek olarak yapılabilmesini sağlamaktadır. Örneğin: karakter olarak girilen bir sayıyı, sayı eşdeğerine çeviren bir fonksiyon yazmak istersek:

atoi(s) /*s'i tamsayıya çevirme*/ 
char s[];
{
  int i,n;

  n=0;
  for(i=0;s[i]>='0'&&s[i]<='9';++i)
	n=10*n+s[i]-'0'; 
  return(n);
}
Bilindiği gibi s[i]-'0' ifadesi, bize s[i]'de depolanmış, karakterin nümerik değerini verir. Çünkü bütün rakamlar karakter setinde (ASCII) birbirlerini izleyen sırayla yeralır.

Bir diğer örnek olarak, giriş karakterlerinden büyük harf olanları küçük harfe dönüştüren lower fonksiyonu verilebilir. lower fonksiyonu, eğer karakter büyük harfse, o karakterin küçük harfini; karakter setinde büyük harfler dışında kalan bir karakterse, karakterin kendisini çağırıcı fonksiyona yollamalıdır. O zaman:

lower(c) /*c karakteri küçük harfe dönüşür*/ 
int c;
{
  if (c>='A'&&c<='Z')
	return(c+'a'-'A');
  else
	return(c);
}
Otomatik tür değişmelerinin başka bir yararı da karşılaştırma ve mantıksal operatörlerin kullanılmasında görülür. i>j veya && ve || operatörleri ile birbirine bağlanan ifadeler doğruysa 1, yanlışsa 0 değerini alırlar. Yani:
i=(c>='0'&&c<='9'); 
ifadesi sonucunda, i değişkeninin değeri ya 1 ya da 0 olabilir. Ayrıca >=, &&, <= operatörlerinin önceliği ='den daha fazla olduğu için parantezlerin yazılmasına da gerek yoktur. if, while gibi komutların test bölümlerinde doğru, 0'dan farklı herhangi bir sayı anlamına gelmektedir.

Aritmetik işlemlerdeki tür değiştirmeler tahmin edilebileceği gibidir. Genel olarak bir aritmetik operatör (+, -, * gibi) iki farklı tür değişken arasında uygulanıyorsa; değişkenlerden düşük türde (bellekte az yer kaplayan) olanı, büyük türde (bellekle daha fazla yer kaplayan) olanına çevrilir ve sonuç büyük türde olur. Türler arasındaki çevrimler, aşağıdaki ilkelere göre yapılır:
1> char ve short değişkenler int'e çevrilir. float ise, double'a çevrilir.
2> Bundan sonra eğer değişkenlerin herhangi biri double ise, diğeri de double'a çevrilir ve sonuç double olur.
3> Aksi halde değişkenlerin herhangi biri long ise. diğeri de long'a çevrilir ve sonuç long olur.
4> Aksi halde değişkenlerin herhangi biri unsigned ise diğeri de unsigned'a çevrilir ve sonuç unsigned olur.
5> Aksi halde değişkenler mutlaka int olmalıdır ve sonuç da int olur.

Burada dikkat edilecek konu, tüm float değerlerinin double'a çevrilmesidir. Yani C dilinde tüm float (Tk. virgüllü sayı) işlemleri çift yoğunlukla yapılır. Çift yoğunlukla anlatılmak istenen, virgülden sonraki basamağın iki kat fazla olması, dolayısıyla sonucun doğruya daha hesaplanmasıdır.

Bu aylık da bu kadar. Gelecek ay ifadelerdeki tür değiştirmelerini, artırma ve eksiltme operatörlerini, bit düzeyli mantıksal operatörleri, eşleme operatörlerini, şartlı ifadeleri ve son olarak da operatör işlem öncelik sırasını toplu olarak göreceğiz. Hoşçakalın.....