C derlenen bir dildir: bir derleyici kaynağınızı sizin CPU'nuz ve işletim sisteminiz için makine koduna çevirene kadar hiçbir şey çalışmaz. Bu adım tek bir komuttur, ama ne yaptığını bilmek çoğu hata mesajını gizemliden apaçık hâle getirir.
İki Komut
Bunu hello.c olarak kaydedin:
#include <stdio.h>
int main(void) {
printf("Merhaba, C!\n");
return 0;
}
Sonra aynı klasörde:
gcc hello.c -o hello
./hello
İlk komut derler. İkincisi sonucu çalıştırır. Windows'ta çalıştırma komutu Komut İstemi'nde hello, PowerShell'de .\hello'dur - ./ öneki yoktur, çünkü Windows varsayılan olarak geçerli dizine bakar ve Unix kabukları bunu bilerek yapmaz.
-o hello'yu atlarsanız gcc çıktıyı a.out (ya da a.exe) diye adlandırır; eski öğreticilerin ./a.out ile bitmesinin sebebi budur. Çıktınızı her zaman adlandırın; dört karaktere mal olur ve kafa karışıklığını önler.
İşte aynı program, her iki adımı da sizin için yapan tarayıcı editöründe:
"Derlemek" Aslında Ne Yapar
gcc hello.c -o hello tek adım gibi görünür. Dörttür ve her biri kendi hata türüyle başarısız olabilir.
1. Ön işleme. Herhangi bir C derlenmeden önce ön işlemci, # ile başlayan her satırı halleder. #include <stdio.h> harfi harfine o başlık dosyasının içeriğiyle değiştirilir; #define makroları genişletilir; #ifdef blokları tutulur ya da silinir. Çıktı, hiç # satırı kalmamış tek bir büyük C dosyasıdır. Bunu görebilirsiniz:
gcc -E hello.c
Bu yüzlerce satır yazdırır - neredeyse hepsi yapıştırılan stdio.h'dir.
2. Derleme. Ön işlenmiş C ayrıştırılır, tür denetimi yapılır ve CPU'nuz için assembly'ye çevrilir. Söz dizimi hataları, tür hataları ve uyarılar buradan gelir.
3. Assembly'ye çevirme. Assembly bir nesne dosyasına dönüşür - diğer dosyaların fonksiyonlarına yapılan çağrıların yerinde yer tutucular bulunan makine kodu.
gcc -c hello.c # hello.o üretir, bağlamadan önce durur
4. Bağlama. Nesne dosyaları C standart kütüphanesiyle birleştirilir, her yer tutucu gerçek bir adresle doldurulur ve sonuç çalıştırılabilir bir dosyadır. "Undefined reference" hataları buradan gelir.
Pratik çıkarım: bir derleme hatası kaynağınızdaki bir satırı gösterir, bir bağlama hatası göstermez, çünkü bağlama her satır çoktan kabul edildikten sonra gerçekleşir.
İlk Günden İtibaren Kullanmaya Değer Bayraklar
Çıplak gcc file.c -o prog, çok fazla tehlikeli kodu sessizce kabul eder. Dört bayrak bunu değiştirir.
gcc -std=c17 -Wall -Wextra -g hello.c -o hello
-Wallyaygın uyarıları açar. Adına rağmen "tüm" uyarılar değildir - makul olan kümedir.-Wextrakullanılmayan parametreler ve bazı karşılaştırma hataları dahil daha fazlasını ekler.-std=c17dil standardını sabitler, böylece kodunuz her makinede aynı anlama gelir. Daha eski materyal takip ediyorsanız-std=c99kullanın.-ghata ayıklama bilgisini korur, böylece bir şey çöktüğündegdbya dalldbgerçek kaynak satırlarınızı gösterebilir.
Eninde sonunda isteyeceğiniz iki tane daha:
-O2yayın derlemeleri için iyileştirmeyi açar. Öğrenirken kapalı bırakın: iyileştirilmiş kodun hatasını ayıklamak daha zordur ve uyarılar bazen kayar.-fsanitize=address,undefined(gcc ve clang), program sınır dışına çıktığı ya da tanımsız davranışa çarptığı anda net bir mesajla durmasını sağlar. Bu, C'deki tek en yararlı öğrenme bayrağıdır.
Uyarıları kendiniz deneyin. Bu program derlenir ve çalışır, ama iki gerçek hatası vardır:
count'a hiç değer verilmedi, dolayısıyla program orada ne bayt varsa onu yazdırır. -Wall ile derleyici bunu söyler: 'count' is used uninitialized. C'de uyarılar neredeyse hiçbir zaman gürültü değildir - onlara henüz çarpmadığınız hatalar gibi davranın.
Birden Fazla Dosya Derlemek
Gerçek programlar dosyalara bölünür. Hepsini gcc'ye geçirin:
gcc -std=c17 -Wall main.c utils.c -o myprog
Ya da her birini ayrı derleyip sonda bağlayın; derleme sistemleri bunu, bir dosyayı değiştirmenin her şeyi yeniden derlememesi için yapar:
gcc -c main.c # -> main.o
gcc -c utils.c # -> utils.o
gcc main.o utils.o -o myprog
Bazı kütüphaneler açık bir bağlama bayrağı ister. Her yeni başlayanın karşılaştığı, matematik kütüphanesidir:
gcc calc.c -o calc -lm
-lm olmadan math.h'deki sqrt'ü kullanmak sorunsuz derlenir ve sonra bağlama zamanında undefined reference to sqrt ile başarısız olur - bildirim başlıktaydı, ama kod kimsenin istemediği bir kütüphanedeydi.
Hataları Okumak
C'nin hataları kısadır ama tutarlıdır. Üç örnek, başlangıçta göreceklerinizin çoğunu kapsar.
Eksik bir noktalı virgül bir sonraki satırda bildirilir, çünkü derleyici okumaya devam etti:
hello.c:5:5: error: expected ';' before 'return'
Düzeltme 5. satıra değil 4. satıra aittir. Bir hata düzgün görünen bir satırı gösterdiğinde, ondan önceki satırı kontrol edin.
Eksik bir başlık, açıkça doğru yazdığınız bir fonksiyon hakkında bir gizem gibi görünür:
hello.c:4:5: warning: implicit declaration of function 'printf'
Bu, derleyicinin printf için hiç bildirim görmediği anlamına gelir, yani #include <stdio.h>'yi unuttunuz. C99 ve sonrasında bu yalnızca bir uyarı değil, bir hatadır.
Bir bağlama başarısızlığının hiç satır numarası yoktur:
/usr/bin/ld: main.o: in function `main':
main.c:(.text+0x1a): undefined reference to `helper'
Derleyici, helper'ın bir yerde var olduğu konusunda size inandı; bağlayıcı baktı ve yok. Ya tanımı hiç yazmadınız, ya farklı yazdınız, ya da onu içeren dosyayı gcc'ye geçirmeyi unuttunuz.
Her zaman ilk hatayı düzeltin. C hataları zincirleme gider - bozuk tek bir satır yirmi mesaj üretebilir ve ilki düzeltildiğinde on dokuzu yok olur.
Çıkış Kodları
main'den return 0 bir süs değildir. Programın çıkış durumudur ve kabuk onu okuyabilir:
Çalıştırdıktan sonra macOS/Linux'ta echo $? (ya da Windows'ta echo %errorlevel%) o sayıyı yazdırır. Betikler ve derleme araçları devam edip etmeyeceklerine karar vermek için onu kullanır. Gelenek kesindir: 0 başarıdır ve sıfırdan farklı olan, sizin seçtiğiniz bir hata kodudur. İsimleri tercih ederseniz stdlib.h, EXIT_SUCCESS ve EXIT_FAILURE tanımlar.
C99'dan beri main'in sonundan return olmadan düşmek return 0 sayılır - ama yazmak daha anlaşılırdır ve diğer her fonksiyon için zorunludur.
Sıkça Sorulan Sorular
Bir C programını nasıl derleyip çalıştırırım?
Kodu hello.c olarak kaydedin, sonra derlemek için gcc hello.c -o hello, çalıştırmak için ./hello komutunu çalıştırın (Windows'ta yalnızca hello). gcc bulunamıyorsa önce bir derleyici kurmanız gerekir.
gcc -o ne yapar?
-o çıktı dosyasını adlandırır. gcc hello.c -o hello, hello adında çalıştırılabilir bir dosya üretir. -o olmadan gcc a.out'a (Windows'ta a.exe) yazar; pek çok eski öğreticinin ./a.out çalıştırmasının sebebi budur.
Hangi gcc bayraklarını her zaman kullanmalıyım?
gcc -std=c17 -Wall -Wextra -g dosyaniz.c -o programiniz. -Wall -Wextra gerçek hataları yakalayan uyarıları açar, -std=c17 dil sürümünü sabitler ve -g hata ayıklama sembollerini korur, böylece bir hata ayıklayıcı kaynağınızı gösterebilir. Bir yayın derlemesinde hız istediğinizde -O2 ekleyin.
C'de "undefined reference to" ne demektir?
Bu bir bağlayıcı hatasıdır: derleyici bir fonksiyona yapılan çağrıyı kabul etti, ama o fonksiyonun tanımı bulunamadı. Yaygın sebepler isimde bir yazım hatası, ikinci bir .c dosyasını derlemeyi unutmak ya da matematik kütüphanesini bağlamadan (-lm) bir matematik fonksiyonu kullanmaktır.