-3

여러 개의 매개 변수를 받아 들여야하는 함수가 있다고 가정 해 봅시다. 여기에서 im coing은 프로토 타입을 선언하지 않고 함수를 만들도록 지정합니다. 코드에서 호출 될 때. 나는 void 매개 변수를 사용하여 parameters 매개 변수의 무작위 수를받습니다. 그러나 이렇게하면 첫 번째 매개 변수의 메모리 주소에 대한 참조가 전달되는 유일한 것이므로 작동하려면 선언해야합니다.가변 개수의 인수에 대해 프로토 타입이없는 함수에서 인수로 void에 대한 포인터

unsigned char result=0; 
unsigned char a=1; 
unsigned char b=2; 
unsigned char c=3; 

char main (void) 
{ 
    for (;;) 
    { 
     result = function (&a, &b, &c); 
     result = function (&c, &b, &a); 
    } 
} 

function (void *vPointer) 
{ 
    return (1); 
} 

또한 내가 선언하고 기능을 (그것도 선언 암시되는 경우)는 호출과 일치하지 않을 때문에 유형 않고 : 내가 코드에서 그들에게 전화 하겠어 같은 순서로 변수.

결과는 함수에서 보낸 첫 번째 매개 변수에 대한 참조이므로 첫 번째 함수 호출에서 다음 주소를 가리키는 경우 작동하지만 두 번째 호출에서는 c, 그리고 그것이 놓이는 곳보다 앞서있는 어떤 기억이든.

누구나 올바른 방법으로 매개 변수를 정렬하는 방법을 알고 계십니까? 또는 함수에서 알 수없는 수의 매개 변수를받는 효과적인 방법은 무엇입니까?

참고 : (...)을 사용하지 마십시오.

+1

당신은 아마도 이것 [C/C++ : 다양한 변수를 넘길 수 있습니다.] (http://stackoverflow.com/questions/205529/cc-passing-variable-number-of-arguments-around) –

+0

'.. .'는 도서관이 아닙니다. 그것은 언어의 일부입니다. ** 사용하십시오! ** 또는 다른 언어를 사용하십시오 (제안은 없습니다). – pmg

+0

명시 적 리턴 유형이없는 함수를 정의하는 경우 반환 유형이'int' 인 경우와 정확하게 * 똑같습니다. C99 이상을 준수하는 컴파일러를 사용하지 않는 한 반환 유형은 선택 사항이 아닙니다. 반환 형식이'int' 인 함수를 정의하면됩니다. 결과를'unsigned char'에 대입하면 암시 적으로 변환됩니다. –

답변

2

모두 C 함수에는 프로토 타입이 있어야합니다. 실제로 필수는 아니지만 사용하지 않는 좋은 이유는 없습니다 (지원하지 않는 ANSI 이전 컴파일러가 없으면 않는 한). (그러나이 대답의 맨 아래를보십시오.)

가변 개수의 인수를 사용하는 함수를 원하면 해당 프로토 타입은 , ...으로 끝나야하며 함수 자체는 <stdarg.h> 메커니즘을 사용하여 인수를 처리해야합니다. 이 경우 정의 된 유형의 인수가 하나 이상 필요하며 그 인수는 다음 인수의 앵커로 사용됩니다. here 등의 문서에 설명되어 있습니다.

입력 할 때 질문을 ""으로 업데이트했습니다. 참고 : (...)와 같은 라이브러리는 사용하지 말아야합니다. ". <stdarg.h>은 독립형 (임베디드) 독립형을 포함하여 모든 C 구현에 필수적인 소수의 헤더 중 하나입니다. 이는 함수, 유형 및 매크로 만 정의하지 않기 때문입니다. 귀하의 C 구현은 그것을 지원해야합니다. 만약 그렇지 않다면, C에 부합하는 구현이 아니기 때문에, 여러분이 사용하고있는 컴파일러를 정확하게 알려주거나, 가변 함수 나 그와 동등한 함수를 다루는 방법을 찾기 위해 문서를 읽어야 할 것입니다. 당신이 정말로 , ...<stdarg.h>을 (혹은 <varargs.h> 이전이), 당신은 모든 사용에 대한 충분한 인수의 고정 된 수와 함수를 정의 할 수 있습니다 사용할 수없는 경우

것은, 다음 발신자가 추가로 널 포인터를 전달합니다.

는 편집 :

이 의견의 새로운 정보를 기반으로 채팅을 업데이트입니다.

영업 이익은 , ... 표기 또는 <stdarg.h>를 사용하여 몇 가지 이유 하지를 들어, 일부 TI의 마이크로 컨트롤러 printf을 구현하는 숙제가있다. 문제의 컴파일러는 분명히 C89/C90을 구현하므로 두 기능을 모두 지원합니다. 이는 임의의 제한 사항입니다.

이 정보는 문제가되어 왔을 것이므로 OP가 정보를 업데이트 할 때까지이 정보를 downvoting해야합니다.

이것을 실현하는 방법은 없습니다. 정확히 , ...이 표준 언어의 일부이고 <stdarg.h>이 표준 라이브러리의 일부입니다.

아마 가장 좋은 방법은, , ...<stdarg.h>를 사용하는 프로그램을 쓰기는 (다양한 va_* 매크로와 va_list 유형을 해결하는) 전처리 단지 출력을 보여줍니다 있도록 컴파일러를 호출하는 것, 그리고 그 모방. 그리고을 사용하면 컴파일러 설명서를 사용하여 variadic 및 non-variadic 함수에 대한 호출 규칙이 호환 가능하다고 가정해야합니다. 다른 말로하면,이 특정 구현이 무엇을하는지 알아 내고, 유사한 작업을 재발 명하십시오.

는 (나는 숙제의 포인트는 표준 기술이 얼마나 더 나은 증명하는 것입니다 바랍니다.)

업데이트 2 :

내가 프로토 타입을 가지고 있어야 모든 C의 기능 이상 썼다. 이것은 실제로이 규칙에 대한 드문 예외 일 수 있습니다. 적어도 이러한 호출 중 하나를 하나 printf가 (숙제에 의해 금지) , ...으로 선언하지 않는 한

printf("Hello\n"); 
printf("x = %d\n", 42); 

가 준수하는 컴파일러에서 진단을 생산해야하며, printf에 대한 눈에 보이는 프로토 타입이 없다. 프로토 타입이 없다면 호출 중 적어도 하나는 정의되지 않은 동작을 갖게됩니다 (특정 컴파일러에서 정의 할 수는 있지만 C 표준에 정의되지 않은 동작).

실제로 숙제 요구 사항을 충족하려면 ANSI C 이전의 컴파일러를 사용하고있는 것처럼 가장해야합니다.

#include <stdarg.h> 

void myfun(int foo, ...) { 
     va_list ap; 
     va_start(foo, ap); 
     // ... 
     va_end(ap); 
} 
당신은 당신이 실제로 (일반적으로 중 사용을 기대하는 인수를 알고 있는지 확인해야합니다

:

+0

@RobertoNovelo : 프로토 타입은 언어별로 필요하지는 않지만, 하지만 1989 표준 또는 그 이후의 표준을 준수한다면 거의 사용하지 않을 것입니다. 프로토 타입이 작성되지 않은 함수 선언 및 정의는 ANSI 이전 코드와의 호환성을 위해서만 언어로 유지되었습니다. –

+0

@RobertoNovelo : 컴파일러는 주어진 호출의 함수 유형을 "추측"하지 않습니다. 그들은 언어 표준에서 주어진 특정한 규칙을 따른다. 호출이 함수 정의와 일치하지 않고 프로토 타입이 보이지 않으면 컴파일러는 일반적으로 오류 메시지를 생성하지 않습니다. 당신은 오해의 소지가있는 코드를 얻습니다. * 매우 좋고 특별한 이유가없는 한 항상 프로토 타입을 사용하십시오. –

+0

대단히 감사합니다! – RobertoNovelo

1

가변 인수 기능을 사용하는 유일한 "깨끗한"방법은 가변 기능을 사용하는 것입니다 예상되는 인수의 수를 나타내는 첫 번째 인수 (예 : "now arguments"라고하는 int 또는 "% d % s : % s"와 같은 형식 문자열)입니다. 2 char *), 또는 최종 종결 인수를 사용합니다 (예 : NULL이 발생할 때까지 인수 읽기).

0

당신은 가변 길이의 배열을 사용할 수 있습니다

unsigned char result=0; 
unsigned char a=1; 
unsigned char b=2; 
unsigned char c=3; 

function (int len, void *vPointer); 

int main (void) 
{ 
    for (;;) 
    { 
     unsigned char args[3]; 
     args[0] = a; 
     args[1] = b; 
     args[2] = c; 
     result = function (3, args); 
     args[0] = c; 
     args[1] = b; 
     args[2] = a; 
     result = function (3, args); 
    } 
    return 0; 
} 

function (int len, void *vPointer) 
{ 
    return (1); 
} 

을하지만 대신 표준 방법, 즉 가변 기능을 사용하는 것이 좋습니다.

// JK

당신은 구조를 사용할 수 있습니다
+0

사실, 함수 호출은 전송 된 매개 변수의 길이를 선언해서는 안됩니다. 아이디어는 List와 같은 것을하고, 함수에서받은 참조를 통해 당신이 그것을 제안하는 방식으로 NULL을 찾을 때까지갑니다. – RobertoNovelo

+0

컴파일러는 함수에 대한 코드를 생성 할 때 함수에 보내는 매개 변수의 수를 추측 할 수 없습니다. 그래서이 경우 직접 처리 할 방법을 고안해야합니다. 즉 매개 변수 나 전역 변수 등으로 보내야합니다. –

+0

@RobertoNovelo : 연결된 목록을 구현하는 방법을 묻고 있습니까? –

0

: -

typedef struct _Params { 
    int m_a; 
    int m_b; 
    int m_c; 
} Params; 

그런 다음 매개 변수를 혼동 할 수 없다. 최대 글자 수만큼 필요합니다.