2017-11-19 15 views
3

terminfo의 매개 변수화 된 문자열 구문 분석기에서 %d 인코딩의 동작을 이해하려고합니다. 관련 매뉴얼 페이지 here이며한다고 -terminfo 매개 변수화 된 문자열 % d 인코딩 동작

%[[:]flags][width[.precision]][doxXs] 
     as in printf, flags are [-+#] and space. Use a ":" to allow the 
     next character to be a "-" flag, avoiding interpreting "%-" as an 
     operator. 

가 있지만 값이 인쇄되어야하며 가장자리의 경우 무엇을해야 할 곳에서에 대해 아무것도 말하지 않는다. 그들은 스택이나 매개 변수화 된 문자열로 전달되는 인수로부터 왔습니까? 또한 여분의 인수가 전달 된 경우 (매개 변수화 된 문자열에서 %d과 같지 않음) 또는 여분의 %d이있는 경우 (매개 변수화 된 문자열이 잘못 되었습니까?) 그 정의되지 않은 동작 또는 구현 정의 또는 정의 어딘가에 정의되어 있습니까?

내가 수동으로 일부 유효하고 유효하지 않은 문자열을 작성하고 출력을 확인하여 어떤 경우를 확인하기 위해 시도했지만 모든 것이 지금까지 그래서 나는 여기에 패턴을 볼 수 없습니다 비트 일치하지 않습니다 - 당신의 예에서 언급

#include <iostream> 
#include <curses.h> 
#include <term.h> 

using namespace std; 

int main() { 
    // single %d prints single argument 
    // => 2 
    auto res = tparm("[%d]", 2); 
    cout << res << endl; 

    // single %d prints single argument and ignores additional 
    // => 2 
    res = tparm("[%d]", 2, 3, 4); 
    cout << res << endl; 

    // multiple %d prints 0 for absent additional arguments 
    // => 2-0-0-0 
    res = tparm("[%d-%d-%d-%d]", 2); 
    cout << res << endl; 

    // multiple %d prints with equal number of arguments prints 
    // first two correctly and rest 0 
    // => 2-3-0-0-0 
    res = tparm("[%d-%d-%d-%d-%d]", 2,3,4,5,6); 
    cout << res << endl; 

    // single value pushed to stack prints from stack 
    // => 2 
    res = tparm("[%p1%d]", 2); 
    cout << res << endl; 

    // single value pushed to stack prints from stack and ignores extra arguments 
    // => 2 
    res = tparm("[%p1%d]", 2,3,4); 
    cout << res << endl; 

    // single value pushed to stack prints from stack and additional prints are 0 
    // if no arguments are provided 
    // => 2-0-0 
    res = tparm("[%p1%d-%d-%d]", 2); 
    cout << res << endl; 

    // single value pushed to stack prints from stack and additional prints 0 
    // even if equal arguments are provided 
    // => 2-0-0 
    res = tparm("[%p1%d-%d-%d]", 2,3,4); 
    cout << res << endl; 

    // single value pushed to stack prints from stack after pop()? 
    // => 100-<garbage> 
    res = tparm("[%p1%d-%c]", 100); 
    cout << res << endl; 

    // pushed to stack via {} and equal arguments provided, prints all 
    // => 2-1-100-200 
    res = tparm("[%{1}%{2}%d-%d-%d-%d]", 100, 200); 
    cout << res << endl; 

    // pushed to stack via {} and %p1 equal arguments provided 
    // prints only stack and rest 0 
    // => 100-2-1-0 
    res = tparm("[%{1}%{2}%p1%d-%d-%d-%d]", 100, 200); 
    cout << res << endl; 
} 
+0

다음 중 어느 것입니까? C 또는 C++? –

+0

"정의되지 않은 동작"과 "구현 - 정의 된 동작"의 차이점은 무엇입니까? –

+0

@ScottHunter는 두 lang이 모두 tparm()을 사용할 수 있기 때문에 중요하지 않습니다. param의 특정 조합에서 ncurses를 사용하여 세그먼테이션 결함이 발생했기 때문에 정의되지 않은 동작을 작성했습니다.문자열하지만 다른 구현 (같은 다른 언어로 다른 lib)에 똑같은 시도했을 때 그것은 완전히 다른 결과를 줬다. (그러므로 잘못되었거나 구현이 정의 된 동작을하고있다.) –

답변

1

한 문제를 그들은 정의되지 않은 행동을 수행한다는 것입니다. 으로 정의되어 있으며, %p1과 같은 명시적인 매개 변수 토큰을 사용하여 푸시 매개 변수를 스택에 전달합니다.이 매개 변수는 %d과 같은 연산자로 팝 할 수 있습니다. 당신은 (어떤 매개 변수 토큰을 갖지 않는) termcap을 위해 ncurses를의 해결 방법에 의존하고, 즉석 있다는 것을 결여, 즉, 매개 변수 목록에서 이상의 매개 변수를 읽어

res = tparm("[%d-%d-%d-%d]", 2); 

시도와 같은 식을 만들 것입니다. 귀하의 예제는 하나의을 제공하므로 C 언어 (가변 길이 인수 목록의 매개 변수 개수가 잘못됨)의 영역에 있습니다. 호출에 추가 매개 변수가 전달 된 경우 일 수 있습니다 (예 : Visual C accepting wrong number of arguments? 참조). 더 적은 수를 사용하면 결과가 외부의 메모리 인 매개 변수 목록에 액세스 할 수 있습니다.

댓글에 대한 응답 : ncurses는 %d의 termcap 스타일 사용을 허용하지 않고 %p1입니다. 그러나 매개 변수의 수를 계산하여 실제 대체를 수행하기 전에 매개 변수 목록을 작성합니다. 가변 길이 인수 목록으로 이들을 처리하므로 응용 프로그램이 주어진 문자열에 대해 잘못된 수의 매개 변수를 전달했는지 여부를 판별 할 수 없습니다.

추가 읽기 :

 
    /* 
    * Analyze the string to see how many parameters we need from the varargs list, 
    * and what their types are. We will only accept string parameters if they 
    * appear as a %l or %s format following an explicit parameter reference (e.g., 
    * %p2%s). All other parameters are numbers. 
    * 
    * 'number' counts coarsely the number of pop's we see in the string, and 
    * 'popcount' shows the highest parameter number in the string. We would like 
    * to simply use the latter count, but if we are reading termcap strings, there 
    * may be cases that we cannot see the explicit parameter numbers. 
    */ 

뿐만 아니라 파라미터 토큰 TERMCAP 부족 등을 수용 tc_BUMP 같은 기능.