2012-05-18 4 views
15

반환 유형이 va_list 인 함수를 작성하고 싶습니다.C에서 va_list를 안전하게 반환합니까?

예 : va_list MyFunc(va_list args);

이 안전하고 휴대용?

+4

'va_list'를 전달하고 수정 한 다음 수정 한'va_list'를 함수에서 반환 할 때 포인터를 va_list에 전달하여 MyFunct()에 전달하는 것이 좋습니다. '포인터를 통해 목록에 작용하게하십시오. 이 표준은 그 기술이 각주에서 허용된다는 것을 구체적으로 언급합니다. –

+0

이것이 내 의도입니다. 표준에서 어디에서 허용 할 수 있습니까? –

+2

필자의 의견으로는'va_list'는 나쁜 생각입니다. 일반적으로 더 안전한 솔루션이 있습니다. 그래서 나는 열심히 생각하고 기능의 설계와 구현에 대한 더 나은 솔루션을 얻게 될 것입니다. –

답변

6

va_list (가능하지는 않지만) 배열 유형이므로 값으로 전달하거나 반환 할 수 없습니다. 이 코드는 마치 첫 번째 요소에 대한 포인터를 전달/반환 할 수 있으므로 호출 수신자에서 매개 변수를 사용할 수 있지만 원본에서 작동 할 수 있습니다.

공식적으로 va_list은 값 유형이 아닌 엔티티 유형이라고 할 수 있습니다. 할당 또는 함수 매개 변수/리턴을 통해 복사하지 않고 va_copy으로 복사합니다.

1

분명히 return 값을 사용할 수 있지만 반환 값을 유용한 방식으로 사용할 수 있는지 확실하지 않습니다. va_list의 취급으로

은 다른없이 하나를 호출 할 수있는 특수 치료 ( va_end()va_start()va_copy() 후 필수), 및 va_start/copyva_end 매크로도이 페어링을 적용 { }를 포함 할 수 있으며, 필요합니다.

+3

'va_copy'는 원본과 별개로 읽을 수있는 * 두번째 *'va_list '객체를 만드는 데 사용됩니다. 여기서는 그렇지 않으므로,'va_list' 객체를 넘겨주고 반환하는 것이 옳다고 말할 수 있습니다. 또한, 표준에서는'va_start()'와'va_end()'가 같은 범위에 있어야한다는 언급이 없기 때문에 어떻게'{': es를 포함 할 수 있는지 알지 못합니다. – Lindydancer

+2

@Lindydancer 오, 그것에 대해 몰랐습니다. [Here] (http://linux.die.net/man/3/va_start) "va_start()의 각 호출은 동일한 함수에서 va_end()의 해당 호출과 일치해야합니다"및 "각 호출 va_copy()는 동일한 함수 내에서 va_end() 호출과 일치해야합니다. "그래서 표준에서 원뿔이라고 생각했습니다. – glglgl

+0

@glglgl :"같은 기능에서 "는 반드시" 동일한 범위 "이므로 매크로가 일치하지 않는 중괄호를 사용할 수 있음을 의미하지는 않습니다. 그러나'va_copy'가'alloca'와 같은 트릭을 사용하는 것을 허용합니다. 왜냐하면 새로운리스트는 함수 리턴을 능가하지 못하기 때문입니다. –

1

언어 표준에 관계없이 실제로 작동하지 않을 수 있습니다. va_list은 호출 수신자가 호출 수신자의 이익을 위해 스택에 저장 한 호출 레코드의 포인터 일 수 있습니다. 피 호출자가 반환되면 스택의 메모리는 재사용을위한 공정한 게임입니다.

va_list 유형을 반환하면 실제로 목록의 내용을 발신자에게 다시 복사하지 않을 수 있습니다. 이것이 C의 유효한 구현 일지라도 표준에서 그렇게해야한다면 표준의 결함 일 것입니다. 다른 함수에 대한 포인터를 전달

+0

'va_list' 매크로가 존재하는 이유는'va_list'가 반드시 스택상의 어떤 것에 대한 포인터 일 필요는 없기 때문입니다. 그렇지 않으면'va_end'는 항상 no-op가됩니다. 'va_list' 객체가 힙에 할당되는 구현이 존재합니다. –

+0

@DietrichEpp 좋은 정보, 나는'va_end'가 한 번에 하나의 반복자만을 허용하는 오래된 윈도우 나 레지스터 윈도우와 관련이 있다고 생각했습니다. 내 대답을 조정했지만 상대적인 강조점 일뿐입니다 ... 대부분의 아키텍처에서는 varargs에 힙을 사용하지 않습니다. – Potatoswatter

0

하지만 그 포인터를 반환 는 매우 다르다. 대부분/대부분의 구현에서는 가변 인수를 vararg 함수가 반환 될 때 파기되는 스택 프레임에 저장합니다. (즉, va_list 또는 에 대한 포인터를 반환하면 이 파괴 된 로컬 변수에 대한 포인터가 남습니다.) - 호 내 경우에는 잘

내가 경고 다시하지만 감사의 va_list를 반환 할 것입니다 - 당신이 기능 MyFunc(va_list *args)va_list에 대한 포인터를 전달하면 Koltuk

Hayri UGUR, 당신은 필요가 없습니다 MyFunc이 원래 목록을 수정하므로 수정 된 (va_arg(*args, type)은) 인수 목록을 다시 전달합니다.

+0

'MyFunc'가 원래 목록을 수정하는지 여부는 지정되어 있지 않다고 생각합니다. 필자는 분명히 두 가지 방식으로 작동하는 구현을 접하게되었습니다. – supercat

+0

@supercat - 어떤 개체에 대한 포인터가 함수로 전달되고 함수가 가리키는 대상 개체를 수정하면 원래 개체가 수정되는 것이 본질적입니다. – Armali

+0

va_list가 (대부분의 플랫폼에서 가장 효율적인 것처럼) 단순 포인터 인 경우 함수에 전달하면 포인터의 복사본이 함수에 전달되고 va_arg는 원본에 영향을주지 않고 포인터의 복사본을 증가시킵니다. – supercat

관련 문제