C'ye giriş: değişkenler, tipler ve operatörler
C programının yapısı, int/char/double, kapsam (scope), tam sayı bölmesi, ++/--, mantık ve bit operatörleri, öncelik. “What is printed?” sorularının temeli.
Dönemin son dört haftası C. Neden C? Çünkü C, şimdiye kadar öğrendiğin seviyenin hemen üstünde durur: bir C değişkeni bellekte bir konumdur, bir C ifadesi birkaç LC-3 komutudur, bir fonksiyon çağrısı JSR ve yığın işlemleridir. Kitap C’yi bu yüzden LC-3’ün üzerine kurar. Sınavda C’den gelen soruların çoğu “What is printed?” tipidir: kodu kafanda çalıştırıp çıktıyı yazarsın.
Altın kurallar:
- int / int = int, ondalık kesilir.
- Doğru = sıfır olmayan, yanlış = 0. Karşılaştırmalar 1 ya da 0 üretir.
- x++ eski değeri, ++x yeni değeri verir.
- && ve || kısa devre yapar.
- Bir blok içinde tanımlanan değişken dışarıdakini gölgeler.
İlk program
#include <stdio.h>
int main(void) {
int count = 3;
printf("count = %d\n", count);
return 0;
}
count = 3
#include <stdio.h>: printf/scanf için preprocessor komutu. Derlemeden önce o dosyanın içeriği buraya eklenir.main: program buradan başlar.- Her deyim
;ile biter. Bloklar{ }.
C programı derlenir (compile): kaynak kod → preprocessor → compiler → assembly/makine kodu → linker → çalıştırılabilir dosya. LC-3 üzerinde bu, 10. haftada yazdığın türden bir assembly üretmek demektir.
Değişkenler ve tipler
Her değişkenin bir tipi, bir adı ve bir değeri vardır. Tip, bellekte kaç bit ayrılacağını ve bitlerin nasıl okunacağını söyler (2. hafta).
| Tip | Ne tutar? | Örnek | printf |
|---|---|---|---|
int | işaretli tam sayı (2’s complement) | int n = -5; | %d |
char | tek karakter (ASCII kodu, küçük tam sayı) | char c = 'A'; | %c ya da %d |
double | ondalıklı sayı (IEEE 754) | double x = 2.5; | %f |
LC-3 C’sinde int 16 bittir; senin bilgisayarında genelde 32 bit. Sınavda kullanılacak sayılar her ikisine de sığar.
Sabitler: 17 ondalık, 0x1F hex (31), 017 sekizlik (15). Başa sıfır koymak sayıyı sekizlik yapar: dikkat.
Kapsam (scope)
- Local değişken: bir fonksiyonun ya da bloğun içinde tanımlanır, sadece orada görülür. LC-3’te yığında (runtime stack) yaşar.
- Global değişken: tüm fonksiyonların dışında tanımlanır, her yerden görülür. LC-3’te global veri bölgesinde yaşar (R4 bu bölgeyi gösterir).
İç kapsamdaki aynı isimli değişken dıştakini gölgeler:
int g = 10;
void show(void) {
int g = 3; /* yeni, yerel g */
printf("show: %d\n", g);
}
int main(void) {
show();
printf("main: %d\n", g);
return 0;
}
show: 3
main: 10
TUZAK · ilk değer verilmemiş local.
int x;yazıp x’i kullanırsan değeri belirsizdir (o bellek konumunda ne kaldıysa). Global değişkenler ise otomatik 0 ile başlar.
Aritmetik operatörler
printf("%d %d %d %d\n", 7 / 2, -7 / 2, 7 % 3, -7 % 3);
3 -3 1 -1
- Bölme sıfıra doğru kesilir: -3,5 → -3.
%sonucunun işareti soldaki sayınınkidir.- Biri double ise bölme gerçek bölmedir:
7 / 2.0= 3.5.
Atama ve bileşik atama
int n = 10;
n -= 3; /* 7 */
n *= 2; /* 14 */
n /= 4; /* 3 */
n %= 3; /* 0 */
printf("%d\n", n);
0
Artırma ve azaltma
| İfade | Değeri | Sonra x |
|---|---|---|
x++ | eski x | x + 1 |
++x | x + 1 | x + 1 |
x-- | eski x | x - 1 |
--x | x - 1 | x - 1 |
int i = 3;
int k = i++ * 2; /* 3 * 2, sonra i = 4 */
printf("%d %d\n", i, k);
4 6
++i * 2 yazsaydın önce i = 4 olur, k = 8.
TUZAK · aynı değişkeni bir ifadede iki kez değiştirmek.
x = x++ + ++x;gibi ifadeler C’de tanımsızdır (undefined behavior). Derleyiciye göre farklı sonuç verir. Sınav sorularında bunlarla karşılaşırsan cevap “undefined” olabilir.
İlişkisel ve mantıksal operatörler
< <= > >= == != sonuç olarak 1 (doğru) ya da 0 (yanlış) verir. && (ve), || (veya), ! (değil) her sıfır olmayan değeri doğru sayar.
int a = 3, b = 0;
printf("%d %d %d %d\n", a && b, a || b, !b, a == 3);
0 1 1 1
Kısa devre (short-circuit): A && B’de A yanlışsa B hesaplanmaz. A || B’de A doğruysa B hesaplanmaz. Bu, (i != 0) && (10 / i > 1) gibi korumalı ifadeleri mümkün kılar.
Koşul operatörü: koşul ? a : b. Koşul doğruysa a, değilse b.
Bit operatörleri
| Operatör | Anlamı | Örnek (12 = 1100, 10 = 1010) |
|---|---|---|
& | AND | 12 & 10 = 8 |
| | OR | 12 | 10 = 14 |
^ | XOR | 12 ^ 10 = 6 |
~ | NOT (her bit) | ~5 = -6 |
<< | sola kaydır | 5 << 2 = 20 |
>> | sağa kaydır | 40 >> 3 = 5 |
~x = -x - 1 (2’s complement). & ile &&’yi karıştırma: 12 & 10 = 8, 12 && 10 = 1.
char aritmetiği
char bir tam sayı olduğu için onunla hesap yapılır:
char c = 'b';
c = c - 'a' + 'A'; /* küçük → büyük */
printf("%c\n", c);
printf("%d\n", '7' - '0');
B
7
Öncelik ve birleşme
| Seviye | Operatörler | Yön |
|---|---|---|
| 1 | () [] -> . x++ x-- | soldan sağa |
| 2 | ++x --x ! ~ -x *p &x (tip) | sağdan sola |
| 3 | * / % | soldan sağa |
| 4 | + - | soldan sağa |
| 5 | << >> | soldan sağa |
| 6 | < <= > >= | soldan sağa |
| 7 | == != | soldan sağa |
| 8 | & | soldan sağa |
| 9 | ^ | soldan sağa |
| 10 | | | soldan sağa |
| 11 | && | soldan sağa |
| 12 | || | soldan sağa |
| 13 | ?: | sağdan sola |
| 14 | = += -= … | sağdan sola |
Emin değilsen parantez kullan; sınavda ise tabloya göre adım adım çöz:
2 + 3 * 4 % 5
2 + 12 % 5 * ve % aynı seviye, soldaki önce
2 + 2
4
C’den LC-3’e
a = b + c; (üçü de local) derleyici tarafından kabaca şöyle çevrilir (R5 frame pointer, 12. hafta):
LDR R0, R5, #-1 ; R0 = b
LDR R1, R5, #-2 ; R1 = c
ADD R0, R0, R1
STR R0, R5, #0 ; a = R0
Yani her C değişkeni bir bellek konumu, her işlem bir ya da birkaç komut.
Sık yapılan hatalar
| Yanlış düşünce | Doğrusu |
|---|---|
7 / 2 = 3.5 | 3; ondalık için 7 / 2.0 |
double d = 7 / 2; → 3.5 | 3.0 |
y = x++ → y yeni değer | y eski değer |
10 > 5 > 1 doğru | (10>5)=1, 1>1 = 0 |
& ile && aynı | & bitsel, && mantıksal |
!5 = -5 | 0; -5 için -5, -6 için ~5 |
017 = 17 | Sekizlik: 15 |
| Local değişken 0 ile başlar | Belirsiz; global 0 ile başlar |
Kendini test et
Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.
What is printed?
printf("%d %d\n", 17 / 5, 17 % 5);Cevabı göster
İki int bölünürse sonuç int, ondalık kesilir: 17 / 5 = 3. Kalan: 17 = 3·5 + 2 → 2.
What is printed?
int x = 5;
int y = x++;
printf("%d %d\n", x, y);Cevabı göster
x++ (post-increment) önce eski değeri verir, sonra artırır. y = 5, x = 6.
What is printed?
int x = 5;
int y = ++x;
printf("%d %d\n", x, y);Cevabı göster
++x (pre-increment) önce artırır, sonra yeni değeri verir. x = 6, y = 6.
What is printed?
double d = 7 / 2;
printf("%.1f\n", d);Cevabı göster
Sağ taraf önce hesaplanır: 7 / 2 iki int → 3. double'a atanınca 3.0 olur. 3.5 için 7 / 2.0 ya da (double) 7 / 2 yazılmalı.
What is printed?
printf("%d\n", 10 > 5 > 1);Cevabı göster
C'de karşılaştırma 1 (doğru) ya da 0 (yanlış) üretir ve soldan sağa yapılır: (10 > 5) = 1, sonra 1 > 1 = 0. Matematikteki gibi zincirleme okunmaz.
What is printed? Does the program crash?
int i = 0;
int r = (i != 0) && (10 / i > 1);
printf("%d\n", r);Cevabı göster
&& kısa devre (short-circuit) yapar: sol taraf 0 ise sağ taraf hiç hesaplanmaz. Bu yüzden 10 / 0 çalışmaz. Sonuç 0.
What is printed?
printf("%d %d %d\n", 12 & 10, 12 | 10, 12 ^ 10);Cevabı göster
12 = 1100, 10 = 1010. AND: 1000 = 8. OR: 1110 = 14. XOR: 0110 = 6. 2. haftadaki maske işlemlerinin aynısı.
What is printed?
printf("%d %d\n", 5 << 2, 40 >> 3);Cevabı göster
Sola k bit kaydırma ile çarpar: 5 · 4 = 20. Sağa kaydırma (pozitif sayıda) 'ya böler: 40 / 8 = 5.
What is printed?
char c = 'A' + 2;
printf("%c %d\n", c, c);Cevabı göster
char bir tam sayıdır: 'A' = 65, 65 + 2 = 67. %c karakter olarak ('C'), %d sayı olarak (67) basar.
What is printed?
printf("%d\n", 2 + 3 * 4 % 5);Cevabı göster
* ve % aynı seviyede, soldan sağa: 3 * 4 = 12, 12 % 5 = 2. Sonra 2 + 2 = 4.
What is printed?
int x = 4;
printf("%d %d %d\n", !x, !!x, x > 3 ? 10 : 20);Cevabı göster
Sıfır olmayan her değer doğrudur. !4 = 0, !!4 = !0 = 1. Koşul operatörü: x > 3 doğru → 10.
What is printed?
int g = 10;
void show(void) {
int g = 3;
printf("show: %d\n", g);
}
int main(void) {
show();
printf("main: %d\n", g);
return 0;
}Cevabı göster
show içindeki int g yeni bir yerel (local) değişkendir ve global g'yi gölgeler (shadowing). Global g'ye dokunulmaz. main global g'yi görür: 10.
Doğrulama: Her kod parçası C99 olarak Zig cc (clang) ile derlenip çalıştırıldı, çıktılar birebir kopyalandı (verify/SEN2201/c/w11a.c; ilk program ve char örneği w11b.c başında; node verify/SEN2201/c/run.mjs w11).