문제

이 코드 조각(요약)...

AnsiString working(AnsiString format,...)
{
    va_list argptr;
    AnsiString buff;

    va_start(argptr, format);
    buff.vprintf(format.c_str(), argptr);

    va_end(argptr);
    return buff;
}

과에 기초하여,그 참조로 전달하는 것은 기본 가능한 경우에,나는 그것을 변경됐어요.

AnsiString broken(const AnsiString &format,...)
{
... the rest, totally identical ...
}

내 호출하는 코드는 다음과 같습니다:-

AnsiString s1, s2;
    s1 = working("Hello %s", "World");
    s2 = broken("Hello %s", "World");

하지만,s1 담"Hello,"세계는 동안 s2 는"안녕하세요(null)".이라고 생각하는 방식으로 인해 va_start 작동 하지만,나는지 정확히 무슨 일이 일어나고 있는지 확.

도움이 되었습니까?

해결책

va_start가 확장되는 것을 보면 무슨 일이 일어나고 있는지 알 수 있습니다.

va_start(argptr, format); 

(대략)

argptr = (va_list) (&format+1);

형식이 값 유형 인 경우 모든 변형 인수 직전에 스택에 배치됩니다. 형식이 참조 유형 인 경우 주소 만 스택에 배치됩니다. 참조 변수의 주소를 취하면 인수의 주소가 아닌 주소 또는 원래 변수 (이 중단기 전에 생성 된 임시 소송의 경우)를 얻습니다.

전체 수업을 통과하고 싶지 않다면 옵션은 포인터를 지나가거나 더미 논쟁을 가하는 것입니다.

AnsiString working_ptr(const AnsiString *format,...)
{
    ASSERT(format != NULL);
    va_list argptr;
    AnsiString buff;

    va_start(argptr, format);
    buff.vprintf(format->c_str(), argptr);

    va_end(argptr);
    return buff;
}

...

AnsiString format = "Hello %s";
s1 = working_ptr(&format, "World");

또는

AnsiString working_dummy(const AnsiString &format, int dummy, ...)
{
    va_list argptr;
    AnsiString buff;

    va_start(argptr, dummy);
    buff.vprintf(format.c_str(), argptr);

    va_end(argptr);
    return buff;
}

...

s1 = working_dummy("Hello %s", 0, "World");

다른 팁

다음은 C ++ 표준 (18.7- 기타 런타임 지원)에 대해 말합니다. va_start() (강조 광산) :

ISO가 두 번째 매개 변수에 배치하는 제한 사항 va_start() 헤더의 매크로 <stdarg.h> 이 국제 표준에서 다릅니다. 매개 변수 parmN 함수 정의의 변수 매개 변수 목록에서 가장 오른쪽 매개 변수의 식별자입니다. ...). 매개 변수 인 경우 parmN 함수, 배열 또는 참조 유형으로 선언됩니다. 또는 매개 변수가없는 인수를 전달할 때 발생하는 유형과 호환되지 않는 유형의 경우 행동은 정의되지 않습니다.

다른 사람들이 언급했듯이, C ++에서 Varargs를 사용하는 것은 비 스트레이트 C 항목 (및 아마도 다른 방식으로)과 함께 사용하면 위험합니다.

즉, 나는 여전히 printf ()를 항상 사용합니다 ...

당신이 원하지 않는 이유 좋은 분석 N0695

C ++ 코딩 표준 (Sutter, Alexandrescu)에 따르면 :

Varargs는 C ++와 함께 사용해서는 안됩니다.

그들은 안전한 유형이 아니며 클래스 유형의 대상에 대해 정의되지 않은 동작을 가지고있어 문제가 발생할 수 있습니다.

내 쉬운 해결 방법은 다음과 같습니다 (Visual C ++ 2010으로 컴파일) :

void not_broken(const string& format,...)
{
  va_list argptr;
  _asm {
    lea eax, [format];
    add eax, 4;
    mov [argptr], eax;
  }

  vprintf(format.c_str(), argptr);
}

Side note:

동작한 클래스 형식으로 varargs 인수가 정의되지 않을 수 있습,그러나 그것의 일관에서 제 경험입니다.컴파일러를 밀어 sizeof(클래스)의 클래스의 메모리에 스택입니다.즉,의사 코드:

alloca(sizeof(class));
memcpy(stack, &instance, sizeof(class);

에 대해 정말 흥미로운 이 예제에서 활용되는 매우 창의적인 방법으로,당신은 을 통과 하는 인스턴스의 장소에서 LPCTSTR 을 varargs 기능 직접 작동하고 있으며,주 참여합니다.나는 그것을 떠나 운동으로 리더는 방법을 알아들이는 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top