2012-01-02 1 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 가변 길이 인수 목록 "The C Programming Language 2nd Edition"의이 코드에는 버그가 있습니까?

에서이다 일반적으로이 프로그램을 출력 AAAAAAA 및 정지해야하지만 대신이 AAAAAAA의 DDDD를 인쇄합니다. http://ideone.com/d3Akk

정말 버그입니까?

감사합니다.

+0

당신의 문제는 당신이 K & R에서 코드를 가져 와서 iso 환경에서 실행하려고한다는 사실과 거의 관련이 있습니다. – Marcin

+2

버그에 대한 정의는 다음과 같습니다 : 예상대로 작동하지 않으면 버그입니다. – nmagerko

+2

왜 K & R은'aaaaaaa '를 출력해야한다고 생각합니까? 텍스트에 그 설명이 포함되어 있습니까? –

답변

2

switch 문 앞에 %이 오면 null 종결자가 무시됩니다. 그것은 버그 일 수도 있고 아닐 수도 있지만 C 함수의 비표준 동작입니다. 그러나, 귀하의 경우, 그것은 정의되지 않은 행동을 일으키지 않으며 그것이 말하는 것을 거의합니다.

1

"aaa %"와 같은 형식 문자열로 호출되는 함수는 UB를 발생시켜 최소한의 놀라움의 원칙을 위반합니다. 이것은 내 책의 버그입니다.

1

for 조건 *p 때문에 첫 번째 NULL에서 멈추는 것이 좋을 것이라고 생각하십니까?

그래서 질문입니다. "왜 첫 번째 NULL에서 멈추지 않습니까?" 응답 : switch() 성명의 사후 증가 때문입니다. 스위치 블록을 먼저 평가 한 다음 포인터를 증가시킵니다. 따라서 특정 경우에 함수가 백분율 기호를 볼 때 switch 문으로 떨어집니다. NULL은 유효한 형식 지정자가 아니기 때문에 스위치 블록은 기본적으로 출력 형식 지정자로 출력됩니다. 그런 다음 후행 증가로 인해 포인터는 한 문자 앞에 이동합니다 (d). 따라서 *p은 0이 아니므로 d으로 작동하므로 for 루프의 조건이 true로 정의됩니다.

편집 : IMO에는 버그가 있지만 실제로는이 것이 아닙니다. 잘못된 형식 지정자가 기본 구문에 의해 자동 삭제됩니다. 또한, minprintf("whoopsie%");과 같은 것을 할 경우 가장자리 경우가있을 수 있습니다. 여기서 for 루프는 문자열의 끝을 반복하여 반복합니다.

+0

''aaaaaaa % \ 0dddd ''와''aaaaaaa % "'는 틀림없이 (다른 끝에 쓰레기가있는) 동일한 C 문자열이기 때문에 동일한 버그라고 주장 할 수 있습니다. - 적어도 strcmp는 알 수 없습니다 떨어져서. – Blaisorblade