2012-01-02 48 views
0
#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
void minprintf(char *fmt, ...) 
{ 
    va_list ap; 
    char *p, *sval; 
    int ival; 
    double dval; 

    va_start(ap, fmt); 
    for (p = fmt; *p; p++) { 
     if (*p != '%') { 
      putchar(*p); 
      continue; 
     } 
     switch (*p++) { 
     case 'd': 
      ival = va_arg(ap, int); 
      printf("%d", ival); 
      break; 
     case 'f': 
      dval = va_arg(ap, double); 
      printf("%f", dval); 
      break; 
     case 's': 
      for (sval = va_arg(ap, char *); *sval; sval++) 
       putchar(*sval); 
      break; 
     default: 
      putchar(*p); 
      break; 
     } 
    } 
    va_end(ap); 
} 

int main(void) 
{ 
    minprintf("aaaaaaa%\0dddd"); 
    return 0; 
} 

此代碼是從C編程語言第二版 7.3可變長度參數列表「C編程語言第二版」中的代碼是否包含錯誤?

通常這個程序應該輸出AAAAAAA和停止,而是它將打印AAAAAAA DDDD。 http://ideone.com/d3Akk

這真的是一個錯誤。

謝謝。

+0

你的問題幾乎肯定與你從K&R獲取代碼並嘗試在iso環境中運行它有關。 – Marcin 2012-01-02 18:58:53

+2

我相信一個bug的定義是這樣的:如果它沒有按預期工作,那就是一個bug。 – nmagerko 2012-01-02 18:59:01

+2

爲什麼K&R認爲它應該輸出'aaaaaaa'?文本是否包含對此的任何解釋? – 2012-01-02 19:11:31

回答

2

如果它的前面有%(在switch語句中),那麼你會忽略空終止符。這可能是也可能不是bug,但對C函數來說肯定是非標準行爲。但是,在你的情況下,它不會導致任何未定義的行爲,並且幾乎沒有它所說的。

1

使用像「aaa%」這樣的格式字符串調用的函數將導致UB,打破最不讓人驚訝的原則。這是我書中的一個錯誤。

1

你的問題是因爲for條件*p你會期望它停在第一個NULL,只有它不?

所以你的問題是:「爲什麼它不停在第一個NULL?」。答:因爲switch()聲明中的後增加。它先評估開關塊,然後遞增指針。那麼在你的具體情況下會發生什麼情況是,當函數看到百分號時,它將落入switch語句中。因爲NULL不是有效的格式說明符,所以開關塊默認輸出它。然後,由於後增加指針向前移動一個字符,這是一個d。因此,*p計算爲d,它不是0,因此for循環中的條件定義爲true。

編輯:那裏有一個錯誤,國際海事組織,但它實際上不是這一個:這是錯誤的格式說明符默認構造丟棄的事實。另外,如果你想做一些類似minprintf("whoopsie%");的for循環,它會試圖迭代超過字符串的末尾!

+0

你可能會認爲它是同一個bug,因爲''aaaaaaa%\ 0dddd''和''aaaaaaa%'''可以說是相同的C字符串(最後有不同的垃圾) - 至少,'strcmp'不能說他們分開。 – Blaisorblade 2016-11-17 19:10:42