2013-10-26 2 views
4

가변 인수가 포함 된 작은 C 프로그램을 작성했습니다. 아래를 참조하십시오 : -가변 인수가있는 함수 - 별난 출력

#include <stdio.h> 
#include <stdarg.h> 

double calculateAverage(int num,...) 
{ 
    va_list argumentList; 
    double sum=0; 
    int i; 

    va_start(argumentList,num); 

    for(i = 0; i < num; i++) 
    { 
    sum += va_arg(argumentList,double); 
    } 
    va_end(argumentList); 
    return(sum/num); 
} 

int main() 
{ 
    printf("%f\n",calculateAverage(3,1,2,3)); 
    printf("%f\n",calculateAverage(4,2,4,6,8)); 
    printf("%f\n",calculateAverage(4,2.0,4.0,6.0,8.0)); 
    printf("%f\n",calculateAverage(3,1,2,3)); 
} 

출력은 다음과 같습니다 내가 특별히 소수점으로 그들을 대표 할 때

0.000000 
0.000000 
5.000000 
5.333333 

calculateAverage(4,2.0,4.0,6.0,8.0), 즉 예상 출력을주고있다.

  • va_arg(argumentList,double) 숫자를 안전하게 2 배로 올리면 안됩니까?

  • calculateAverage(3,1,2,3)은 2 개의 다른 장소에서 2 개의 결과를 어떻게 낼 수 있습니까? 나는 '정의되지 않은 행동'영역 안에 있습니까? 그렇다면 어떻게?

gcc 버전 4.8.1을 사용하고 있습니다. 당신이 double로 해석하려고하기 때문에

답변

2

아니요, 아니요. va_arg()을 사용하면 데이터의 형식을 알 수 있습니다. 내부 표현과 관련하여 1.01과 완전히 다른 것으로 보입니다. 그리고 1double으로 사용하면 완전히 잘못된 것이 있습니다. 그런 다음

double calculateAverage(int num,...) 
{ 
    va_list argumentList; 
    double sum=0; 
    int i; 

    va_start(argumentList,num); 

    printf("%p", &num); 
    unsigned char * c = &num; 
    for(i = 0; i < num * sizeof(double) + 4; i++, c++) 
    { 
    printf(" %02x", *c); 
    } 
    printf("\n"); 
    for(i = 0; i < num; i++) 
    { 
    sum += va_arg(argumentList,double); 
    } 
    va_end(argumentList); 
    return(sum/num); 
} 

,

printf("%f\n",calculateAverage(3,1,2,3)); 

0xbfc507d0 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ... 
-0.054776 

반면
printf("%f\n",calculateAverage(3,1.0,2.0,3.0)); 
을 제공합니다 : 여기

는 함수 호출을 실행할 때 스택에 일어나는 것이다 정수 1 내부 내부 00 00 00 00 00 00 f0 3f (a 리틀 엔디안의 시스템에서 모두) 모양 등 00 00 00 011.0 반면 보이기 때문에 0

0xbfd15290 03 00 00 00 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 00 40 00 00 00 00 00 00 08 40 
2.000000 

준다.

00 00 00 01 00 00 00 02과 같은 스택 내용을 해석하면 이상한 결과가 발생할 수 있습니다.

2

문제는이 문 sum += va_arg(argumentList,double);

함께 - 문제가 Integer literals으로 발생합니다. intdouble으로 전송하면 정상적으로 작동합니다.

printf("%f\n",calculateAverage(3,(double)1,(double)2,(double)3)); 
printf("%f\n",calculateAverage(4,(double)2,(double)4,(double)6,(double)8)); 
printf("%f\n",calculateAverage(4,2.0,4.0,6.0,8.0)); 
printf("%f\n",calculateAverage(3,(double)1,(double)2,(double)3)); 

va_arg함수에 전달 된 인자의 실제 유형을 결정하지만, 그 종류와 타입 매크로 인수로서 전달 된 모든 유형 사용 할 수 없다.

+1

또는 형식 캐스트 수가 많지 않고 가독성을 높이기 위해 숫자에 소수 자릿수를 추가 할 수 있습니다. 예 : 3 -> 3.0 –

+0

@PatTeen - 짧고 달콤합니다. – Sadique

2

가변 인자 함수의 인수 촉진 일반 규칙을 따른다 : int (char, short 등)보다 작은 유형 int 승진되며 floatdouble로 승격되어 있지만, intdouble 승진하지 않을 때문에,이

va_arg(argumentList,double) 

인수 유형 double입니다 컴파일러를 알려줍니다,하지만 일부 호출에서 그들은하지 않습니다. double으로 승격되기 때문에 float을 전달할 수 있습니다.

calculateAverage(4,2.0f,4.0f,6.0f,8.0f); 

솔루션은 당신이 double 매개 변수를 전달하고 있는지, 또는 예를 들어, 형식 문자열, parmN의 다른 종류를 사용 중입니다. (printf 중 하나와 동일)