請教關於c語言printf和指標的問題

時間 2022-04-11 19:53:03

1樓:匿名使用者

printf("%f",p) (首先說明,這種輸出在邏輯上是不通的) ----------的確,這樣書是錯誤的用法!!

我也測試了一下,如果這樣寫:

printf("%f %f\n",*p,*p); //10.09996 10.099996

printf("%f %f\n",*p,p); //10.09996 10.09996 error1

printf("%f %f\n",p,p); //0.000 ok 10.09996 error2

printf("%f\n",p); //0.000 這是正常的輸出

printf("%f\n",p); //0.000 這是正常的輸出

因此,我覺得這是printf函式的bug,究竟為什麼 等高人吧

既然知道什麼是正確的用法,就採用正確的用法好了!!!學會正確使用c函式是很必要的!

2樓:

有意思的發現。要說是printf的bug不如說是c的缺陷。

首先說的基本依據:1、c壓棧順序是從右到左,也就是前面的引數位置比較低;2、c語言規定所有float引數在傳遞過程全部轉化成double,這大概是歷史原因吧;3、關於可變引數,編譯器不進行檢查,也沒有能力檢查,它只是把引數全數壓棧,正確與否全賴程式設計師了,還是那句話,c認為程式設計師永遠是對的;4、既而,像printf、scanf等等函式根本無法知道究竟傳給它的是神馬引數,也就無從談檢查格式串與引數是否匹配,所以儘管printf("%f\n",p)不合邏輯,甚至printf("%f%f%f%f\n",p)除了看**的人,我目前只知道的是lint程式能夠做這種檢查;5、gcc的堆疊結構比較特別,gcc函式在入口處直接開出足夠的棧幀空間,因此只要執行點在函式裡,實際上堆疊指標位置就始終不動,turbo c不是這樣的,vc沒看過不知道,我一直不知道gcc這樣是優點還是缺點;6、要看是神馬機子,32位機子上指標4位元組,double浮點數8位元組(是指標的2倍),符號指數等重要的部分在高位元組,低位元組是精度部分。

進入正題,這段**的特點就是全部是printf呼叫,所以在gcc中編譯相當於後面呼叫的引數會重疊覆蓋在前面呼叫的引數的位置上。每次printf期望的引數是(除了前面的格式串)兩個double共16位元組,第二次呼叫給足了16位元組,後續3次呼叫實際上沒有給足數量的位元組數,所以printf用了前面遺留的沒有被覆蓋掉的浮點數 *p 的高4位元組,而低4位元組給覆蓋掉了,結果影響了小數點後面靠後的一點精度改變了。所以關鍵還是在前一次呼叫留下的有些痕跡沒有被覆蓋掉,後一次呼叫給錯引數時printf重用了這些痕跡。

lz可以試試在printf語句之間插入一些至少含有3個double引數的其他函式呼叫,就可以看出效果來了。

3樓:匿名使用者

printf("%f",p)為什麼有時候能把輸出正確的數值,有時候不可以?

- p在32位機器32位編譯器的平台上是32位整數,強制按照浮點型別輸出時會因不同編譯器對printf函式內部**的不同而造成結果異常。

- 這既不是因為printf內部對浮點數精度處理有誤,也不是bug。

如何讓它顯示出正確的數值?

- 在格式輸出之前對p進行強制型別轉換,比如:printf("%f", (double)(unsigned int)p);

- 在無所謂精度的前提下,double可換成float,unsigned int可換為int/short/long/unsigned short/unsigned long等等。

- 理論上而言,後一層型別轉換應當是由編譯器隱式執行的。但如果僅使用一層double/float型別轉換,gcc會報告「應當使用浮點型別時使用了指標型別」(比如程式設計師漏寫了*)的錯誤。

4樓:匿名使用者

輸出數值的誤差主要是因為計算機採用二進位制,對浮點數的處理精度不夠造成的,屬於正常的現象,可以通過控制輸出小數字數來顯示正確的結果。

printf("%f\n",p);想要輸出的是變數在記憶體中的位址,但是位址是整型的,%f不會對型別進行轉換,輸出的結果一般都是不對的。

關於C語言printf()函式格式說明的問題

對於浮點輸出格式來說 m.nf 其中m是輸出寬度,n是精度,f是格式化控制符m指定的是輸出數字字串的 最小長度 比如你輸出 printf 2.3f 123.456 由於實際輸出的數字123.456 共有7個字元,大於2個字元數量 所以這裡的2其實實際上沒起到什麼作用,不過如果你printf 8.3f...

請教下面C語言編寫的printf 裡的式子看不明白呀?剛學!辛苦給教下唄

請重新編譯以後再執行程式,因為照這個程式,執行的結果應該是輸出41才對的 include int main int a,b,c scanf d d d a,b,c printf d n a b?a c?a c b c?b c return 0 因為現在的a 32,b 41,c 38 所以,a b為假...

請教c語言關於位址的輸出問題,請教C語言關於位址的輸出問題

孤狼騰龍 第乙個 printf p a 這是輸出a的值 printf p a 這是主輸出存放a值的位址 第二個 如果填b輸出的是a的位址 要輸出指標變數b的位址就直接printf p b 第三個 scanf d a 這是賦值語句,就是將輸入的數字存放在位址a中 記住有 符號,表示位址 牧蕙蘭 第乙個...

關於c語言陣列和指標的問題,關於C語言陣列和指標的乙個問題

c 語言裡 1 形式邏輯不成立。2 要分清 乙個形式 出現在 宣告裡,還是 出現在語句裡,3 另外,字元變數 與 普通變數 有些 不同。下面只談字元 宣告 char s 10 hello s 是 陣列,初始化 hello 0 自動加 0 宣告 char p p 是 指標。宣告 char p s p ...

關於c語言的累加i和,關於C語言的累加,i 和 i

先說下i 和 i的區別 i 是後加加,先做運算,之後i自加1,i是i先自加1,再做運算。第乙個問題,列印 a 時,先運算就是先列印,之後a自加1,所以列印出來是1 第二個問題,滿屏的1是因為你的迴圈結束條件不對,就是無限迴圈,造成滿屏都是1 第一次迴圈 i 10,輸出10,10自加1為11,i i ...