2012-08-17 4 views
1

안녕하세요! 다음 코드에 대해 몇 가지 의문점이 있습니다.va_list 프로 시저의 루프에서 계속 목적없이 사용함 (?) K & R

[1] for 루프의 중간 조건은 무엇을 의미합니까? ; *p;; *sval; - 입력 문자열의 끝에 도달 했습니까? 그렇다면 어떻게 결정됩니까?

[2] 복잡한 for 루프를 이해하지 못합니다.

조건이 만족스럽지 않으면 *p == %이라고 가정 해 봅시다. 바로 전환하겠습니다. 이제 반대 사례를 생각해 봅시다. %에도 불구하고 다른 모든 문자를 입력하겠습니다. 계속 사용하면 계속 진행하고 그 후에는 switch으로 이동하십시오. 이 두 가지 경우의 차이점은 무엇입니까? 내가 STH와 정말 잘못된해야하지만 지금은 2 시간 이상 내 실수를 찾을 수 없습니다 ...

#include <stdarg.h> 
/* minprintf: minimal printf with variable argument list */ 
void minprintf(char *fmt, ...) 
{ 
    va_list ap; /* points to each unnamed arg in turn */ 
    char *p, *sval; 
    int ival; 
    double dval; 

    va_start(ap, fmt); /* make ap point to 1st unnamed arg */ 

    for (p = fmt; *p; p++) {   /* [1] */ 
     if (*p != '%') { 
      putchar(*p); 
      continue;    /* [2] */ 
     } 
     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); /* clean up when done */ 
} 

도움이 크게 감사합니다!

답변

1

우리가 continue 일 때 문자를 인쇄하고 스위치를 모두 건너 뜁니다. 루프는 형식 선을 통해 (1) 종결 0 또는 (2) 퍼센트 기호를 찾습니다. 착신 제로에 도달하면

는 루프가 종료 :

퍼센트 부호 도달
for (p = fmt; *p; p++) 
//   ^^^ Here is the condition: *p != 0 is implied 

다음 심볼 포맷 문자로 촬영하고, 다음의 가변 인자가에 따라 해석된다.


이 프로그램에는 버그가 있습니다. 백분율 기호가 형식 문자열의 마지막 문자 일 때 형식 문자열 끝에 도달하면 읽지 않습니다 (정의되지 않은 동작). 이 시도 :

minprintf("%\0bug!bug!bug!"); 

마커 \0 스킵되고 bug!bug!bug! 출력이 생성된다 끝 라인 시뮬레이션. 그 이유는 switch 문 머리글에 p의 조건부 pre_increment입니다. 이 문제를 해결하려면 switch에 다음과 같은 경우를 추가

case '\0': 
    p--; // reverse the ++p from the header of the switch 
    break; 
+0

감사합니다. 그 버그에 대한 질문이 있습니다. \ 0을 건너 뛰는 이유는 무엇입니까? 그리고 우연한 % \ 0과 설명 된 동작은 오류가 아닙니다. 그 \ 0을 생략하고 그 뒤에 단어를 인쇄합니다.% \ 0이 문자열의 끝 부분에 있으면 printf는 발생하지 않으며 올바르게 끝납니다. 내가 맞습니까? –

+0

@ PeterKowalski '%'로 끝나는 문자열을 전달하면. ''Hello % "','miniprintf'는 금지 된 문자열의 끝을지나 읽습니다. NULL 종료를 넘어서는 읽기가 발생한다는 요지를 설명하기 위해 문자열 리터럴의 중간에 0을 넣습니다. 프로그램이 항상 크래시되지 않을 수도 있습니다. 정의되지 않은 동작으로 인해 의도하지 않은 결과가 발생할 수 있으므로 항상 피해야합니다. – dasblinkenlight

+0

확인. 지금은 이해. 그러나, post-decrement 대신에 -p가되어서는 안됩니까? –

1

* P * sval이 - 문자열의 문자에 포인트를 역 참조 포인터. C 문자열은 "\ 0"기호로 끝납니다. 그래서 우리가 p, sval point가 0 인 곳에서 얻은 값이 분명히 문자열 끝에 도달했다면

2 continue를 사용하여 그 다음의 모든 명령문을 건너 뛰고 실행 (;; 문)

1
  • [1] null을 반환 할 때까지 루프를 계속합니다. '\0' 문자열입니다.
  • [2]는 문자가 아닌 문자 인 '%'을 인쇄합니다. 문자열의 '%' 다음 문자가 목록에서 다음 va_arg을 인쇄하는 방법을 식별하면.