#include <stdio.h>
int main() {
float a = 1234.5f;
printf("%d\n", a);
return 0;
}
Bir 0
!! Bu nasıl mümkün olabilir? Gerekçe nedir?
Ben kasten bir koyduk %d
içinde printf
davranışını incelemek için deyimi printf
.
Yanıtlar:
Bunun nedeni bir %d
beklemesidir, int
ancak siz bir şamandıra sağladınız.
Şamandırayı yazdırmak için %e
/ %f
/ öğesini kullanın %g
.
Neden 0'ın yazdırıldığına dair: Kayan nokta numarası, double
gönderilmeden önce dönüştürülür printf
. Little endian'da çift gösterimde 1234,5 sayısı
00 00 00 00 00 4A 93 40
A %d
, 32 bitlik bir tamsayı kullanır, bu nedenle sıfır yazdırılır. (Bir test printf("%d, %d\n", 1234.5f);
olarak çıktı alabilirsiniz 0, 1083394560
.)
Neden 6.5.2.2 / 7'den prototip olan printf'e float
dönüştürüldüğüne gelince,double
int printf(const char*, ...)
Bir işlev prototip tanımlayıcısındaki üç nokta gösterimi, argüman türü dönüşümünün bildirilen son parametreden sonra durmasına neden olur. Varsayılan bağımsız değişken yükseltmeleri, takip eden bağımsız değişkenler üzerinde gerçekleştirilir.
ve 6.5.2.2/6'dan itibaren,
Çağrılan işlevi belirten ifade, prototip içermeyen bir türe sahipse, her bağımsız değişkende tamsayı yükseltmeleri gerçekleştirilir ve türe sahip bağımsız değişkenler
float
yükseltilirdouble
. Bunlara varsayılan bağımsız değişken yükseltmeleri denir .
(Bunu öğrendiği için teşekkürler Alok.)
printf
değişken bir fonksiyondur ve standart, değişken fonksiyonlar için a'nın geçmeden önce float
dönüştürüldüğünü söyler double
.
printf()
çağırır .
Teknik olarak hiçbir orada konuşma , her kütüphane uygular kendi ve bu nedenle, çalışmanın çalışmakla yönteminiz sen çok kullanmak gitmiyor ne yaptığını yaparak davranış 'ın. Sisteminizin davranışını incelemeye çalışıyor olabilirsiniz ve eğer öyleyse, belgeleri okumalı ve kitaplığınız için mevcutsa kaynak koduna bakmalısınız . printf
printf
printf
printf
Örneğin, Macbook'umda çıktıyı 1606416304
programınızla alıyorum .
Bir geçerken, söyledikten float
variadic işleve, float
bir şekilde geçirilir double
. Yani, programınız a
bir double
.
Bir bayt incelemek için double
, gördüğünüz bu cevabı burada SO üzerinde son soruya.
Hadi bunu yapalım:
#include <stdio.h>
int main(void)
{
double a = 1234.5f;
unsigned char *p = (unsigned char *)&a;
size_t i;
printf("size of double: %zu, int: %zu\n", sizeof(double), sizeof(int));
for (i=0; i < sizeof a; ++i)
printf("%02x ", p[i]);
putchar('\n');
return 0;
}
Yukarıdaki programı çalıştırdığımda şunu elde ederim:
size of double: 8, int: 4
00 00 00 00 00 4a 93 40
Yani, ilk dört baytı double
0 çıktı, bu yüzden aramanızın 0
çıktısını almış olabilirsiniz printf
.
Daha ilginç sonuçlar için programı biraz değiştirebiliriz:
#include <stdio.h>
int main(void)
{
double a = 1234.5f;
int b = 42;
printf("%d %d\n", a, b);
return 0;
}
Yukarıdaki programı Macbook'umda çalıştırdığımda şunu elde ederim:
42 1606416384
Bir Linux makinesindeki aynı programla şunu elde ederim:
0 1083394560
int
argümanların argümanlardan farklı kayıtlarda geçirilmesinden dolayı double
. printf
ile 42 %d
olan int
argümanı alır ve %d
ikinci int
argüman olmadığından muhtemelen ikinci önemsiz yazdırır .
%d
belirteci söylerprintf
bir tamsayı beklemek. Dolayısıyla, float'ın ilk dört (veya platforma bağlı olarak iki) baytı bir tamsayı olarak yorumlanır. Sıfır olurlarsa, sıfır yazdırılır
1234.5'in ikili gösterimi şuna benzer
1.00110100101 * 2^10 (exponent is decimal ...)
float
Aslında IEEE754 çift değerlerini temsil eden bir C derleyicisiyle , baytlar (hata yapmazsam)
01000000 10010011 01001010 00000000 00000000 00000000 00000000 00000000
Çok az dayanıklı (yani en önemsiz bayt önce gelen) bir Intel (x86) sisteminde, bu bayt dizisi ilk dört bayt sıfır olacak şekilde tersine çevrilir. Yani neprintf
çıktı ...
IEEE754'e göre kayan nokta gösterimi için Bu Wikipedia makalesine bakın .
Bunun nedeni, ikili sayıdaki bir kayan noktaların temsilidir. Bir tam sayıya dönüştürme onu 0 olarak bırakır.
Tanımlanmamış davranışı çağırdığınız için: printf () yönteminin sözleşmesini parametre türleri hakkında yalan söyleyerek ihlal ettiniz, böylece derleyici ne isterse yapmakta özgürdür. Programın çıktısını "dksjalk is a ninnyhead !!!" yapabilir. ve teknik olarak yine de doğru olacaktır.
Nedeni, bu printf()
oldukça aptalca bir işlev. Türleri hiç kontrol etmez. İlk argümanın bir olduğunu söylerseniz int
(ve %d
bununla birlikte söylediğiniz şey budur ), size inanır ve yalnızca bir için gereken baytları alır int
. Bu durumda, makinenizin dört bayt int
ve sekiz bayt kullandığını varsayarsak double
( içeriye float
dönüştürülür ), ilk dört baytı yalnızca sıfır olur ve bu yazdırılır.double
printf()
a
%d
ondalık
%f
yüzer
bunlardan daha fazlasını burada görün .
0 alıyorsunuz çünkü kayan sayılar ve tam sayılar farklı şekilde temsil ediliyor.
Yalnızca ilgili veri türüyle (int, float, string, vb.) Uygun biçim belirticisini (% d,% f,% s, vb.) Kullanmanız gerekir.
Tam sayı değil. Kullanmayı deneyin %f
.