C “format ‘%d’ expects argument of type ‘int *’” uyarısı, scanf içinde %d biçim belirtecine bir int değişkeninin kendisi yerine adresinin verilmesi gerektiğini bildirir. scanf, klavyeden okuduğu değeri doğrudan değişkene değil, değişkenin bellekteki adresine yazar.
Bu nedenle scanf("%d", yas); kullanımı tür uyuşmazlığı uyarısına yol açabilir. Doğru kullanım, değişkenin adresini gönderen scanf("%d", &yas); biçimidir.
Bu scanf uyarısı ne anlama gelir?

Bu uyarı, %d ile beklenen türün int * olduğu, fakat scanf çağrısında farklı bir tür gönderildiği anlamına gelir. Buradaki yıldız işareti, scanf fonksiyonunun bir int değerini değil, o değerin bellekteki adresini beklediğini gösterir.
scanf çağrısının ilk argümanı biçim dizgesidir. Biçim dizgesinden sonraki argümanlar, bu dizgede bulunan belirteçlerle sırayla eşleştirilir. Örneğin scanf("%d", yas); çağrısında %d ikinci argümanı kontrol eder. yas bir int olduğu için derleyici, beklediği int * ile verilen int arasında uyuşmazlık görür.
Derleyici tanısında genellikle kaynak dosyanın adı, satır numarası, sütun numarası ve uyarı seviyesi bulunur. Örneğin dosya adı hatanın hangi kaynak dosyada olduğunu, satır ve sütun bilgisi ilgili çağrının nerede başladığını gösterir. warning ifadesi bunun bir uyarı olduğunu belirtir. GCC, -Wall seçeneğiyle printf ve scanf çağrılarındaki biçim belirteci ve argüman türlerini kontrol eder. Ayrıntılar GCC uyarı seçenekleri belgelerinde açıklanır.
Uyarı mesajındaki “argument 2” ifadesi, scanf fonksiyonunun ikinci argümanını anlatır. Biçim dizgesi birinci argüman olduğu için scanf("%d", yas); çağrısında yas, ikinci argümandır. Birden fazla değer okunuyorsa her argüman, biçim dizgesindeki karşılık gelen belirteçle ayrı ayrı değerlendirilir.
& işareti uyarıyı nasıl düzeltir?
& operatörü, bir değişkenin bellekteki adresini verir. scanf de okuduğu değeri bu adrese yazar. Bu yüzden int değişken için %d kullanırken &yas, double değişken için %lf kullanırken &ortalama gönderilir.
Aşağıdaki kodda adres operatörü eksiktir. Kod derlenirken biçim uyarısı alınabilir ve çalıştırılması güvenli değildir:
#include <stdio.h>
int main(void) {
int yas;
double ortalama;
printf("Yaş ve not ortalamasını girin: ");
scanf("%d %lf", yas, ortalama);
printf("Yaş: %dn", yas);
printf("Not ortalaması: %.2fn", ortalama);
return 0;
}
Bu dosyayı yanlis.c adıyla kaydettiysen derleme komutu şöyledir:
gcc -Wall yanlis.c -o yanlis
Buradaki sorun yalnızca bir uyarı metni değildir. scanf, yas ve ortalama değişkenlerinin adreslerini beklediği hâlde değerlerini alırsa tanımsız davranış oluşabilir. Program yanlış sonuç üretebilir, beklenmedik biçimde sonlanabilir veya bazı çalıştırmalarda farklı davranabilir.
Düzeltilmiş programda iki değişkenin adresi & ile gönderilir. Ayrıca scanf dönüş değeri kontrol edilerek iki girdinin de okunup okunmadığı anlaşılır:
#include <stdio.h>
int main(void) {
int yas;
double ortalama;
printf("Yaş ve not ortalamasını girin: ");
if (scanf("%d %lf", &yas, &ortalama) != 2) {
printf("Geçerli bir giriş yapılmadı.n");
return 1;
}
printf("Yaş: %dn", yas);
printf("Not ortalaması: %.2fn", ortalama);
return 0;
}
Bu programı notlar.c adıyla derlemek için gcc -Wall notlar.c -o notlar komutunu kullanabilirsin. 21 87.5 girdisiyle program, yaş değerini 21, not ortalamasını ise iki ondalık basamakla 87.50 olarak yazdırır.
scanf biçim belirteçleri hangi türlerle eşleşir?

scanf içindeki biçim belirteci, okunacak girdinin nasıl yorumlanacağını ve değerin hangi türdeki değişkene yazılacağını belirtir. Örneğin %d tam sayı okumak için kullanılır ve karşılığında bir int değişkeninin adresi beklenir.
| Biçim belirteci | Değişken türü | Beklenen adres türü | Örnek kullanım |
|---|---|---|---|
%d |
int |
int * |
scanf("%d", &yas); |
%f |
float |
float * |
scanf("%f", &puan); |
%lf |
double |
double * |
scanf("%lf", &ortalama); |
%c |
char |
char * |
scanf("%c", &harf); |
Tablodaki * işareti, beklenen argümanın ilgili türde bir değişkenin adresi olduğunu gösterir. Örneklerde & operatörü, okunacak değerin yazılacağı değişkenin adresini verir.
scanf ile double türünde bir değer okurken %lf kullanmalısın. printf ile ekrana yazdırırken %f kullanılabilmesi kafa karıştırabilir: printf bir değeri alırken scanf değerin yazılacağı adresi alır ve bu adresin türü belirteçle eşleşmelidir.
%c ise sıradaki karakteri, boşluk veya satır sonu olsa bile okuyabilir. Bir önceki girişten kalan boşluk karakterlerini atlayıp sonraki karakteri okumak için scanf(" %c", &harf); yazabilirsin. Belirteçten önceki boşluk, sıradaki boşluk karakterlerinin atlanmasını sağlar.
char dizisi %s ile nasıl okunur?
%s, bir sözcüğü karakter dizisine okumak için kullanılabilir. Dizinin sınırını aşmamak için belirtece alan genişliği eklemek ve okumada dizinin adını kullanmak gerekir.
#include <stdio.h>
int main(void) {
char isim[20];
printf("Ismini gir: ");
if (scanf("%19s", isim) == 1) {
printf("Merhaba, %s!n", isim);
} else {
printf("Isim okunamadi.n");
}
return 0;
}
Örneğin girdi olarak Deniz yazıldığında çıktı şöyle olur:
Ismini gir: Deniz
Merhaba, Deniz!
%19s, en fazla 19 baytlık girdi okur. Böylece isim[20] dizisinde, karakter dizisinin bittiğini gösteren ' ' sonlandırıcısı için de bir bayt yer kalır. Girdi daha uzunsa okunmayan kısmı sonraki giriş işlemleri için akışta kalır.
Bu çağrıda isim dizi adı, dizinin ilk elemanını gösteren bir işaretçiye dönüşür ve %s için uygun adresi sağlar. &isim ise dizinin tamamına yönelik, farklı türde bir işaretçi üretir; bu nedenle burada kullanılmamalıdır.
%s baştaki boşluk karakterlerini atlar ve okumaya başladıktan sonra bir boşluk karakterine geldiğinde durur. Ad ve soyadı gibi birden fazla sözcük içeren bir satırı okumak için fgets değerlendirilebilir.
Sık Sorulan Sorular
scanf uyarısını görmezden gelirsem program neden çökebilir?
Biçim belirteciyle verilen argüman uyuşmadığında scanf geçerli bir adres yerine uygun olmayan bir değer kullanabilir veya belleğe yanlış türde veri yazmaya çalışabilir. Bu durum tanımsız davranışa yol açar; program çökebilir, yanlış sonuç üretebilir ya da farklı bir davranış gösterebilir.
scanf ile double okurken neden %lf kullanılır?
scanf içindeki %lf, okunacak değerin bir double değişkeninin adresine yazılacağını belirtir. %f ise float değişkeninin adresini bekler.
scanf içinde %s kullanırken neden dizi adının önüne & konmaz?
Karakter dizisinin adı, bu çağrıda dizinin ilk elemanını gösteren ve %s için uygun olan adrese dönüşür. Dizi adının önüne & koymak ise farklı türde bir adres oluşturur.
Bir scanf uyarısını incelerken biçim belirtecini, değişkenin türünü ve çağrıya verilen adresi birlikte kontrol edebilirsin.