va_end는 정확히 무엇입니까? 항상 전화해야합니까?
va_end
-재설정 할 매크로arg_ptr
.
가변 인수 목록에 액세스 한 후 arg_ptr
포인터는 일반적으로로 재설정됩니다 va_end()
. 나는 당신이 목록을 반복하고 싶다면 그것이 필요하다는 것을 이해하지만, 당신이 그렇게하지 않을 경우 정말로 필요합니까? 규칙 "항상 default:
당신의 switch
" 와 같은 좋은 습관 입니까?
va_end
정리하는 데 사용됩니다. 스택을 부수고 싶지 않습니까?
에서 man va_start
:
va_end ()
va_start ()의 각 호출은 동일한 함수에서 va_end ()의 해당 호출과 일치해야합니다. va_end (ap) 호출 후 변수 ap는 정의되지 않습니다. va_start () 및 va_end ()로 각각 괄호로 묶인 목록의 여러 순회가 가능합니다. va_end ()는 매크로 또는 함수일 수 있습니다.
must 라는 단어의 존재에 유의하십시오 .
무엇 va_start()
을하고 있는지 모르기 때문에 스택이 손상 될 수 있습니다. va_*
매크로는 블랙 박스로 취급하기위한 것입니다. 모든 플랫폼의 모든 컴파일러는 원하는 것을 할 수 있습니다. 아무것도하지 않거나 많은 일을 할 수 있습니다.
일부 ABI는 레지스터의 처음 몇 개의 인수와 스택의 나머지 인수를 전달합니다. A va_arg()
더 복잡 할 수 있습니다. 주어진 구현이 어떻게 varargs를 수행하는지 찾아 볼 수 있습니다. 이것은 흥미로울 수 있지만 이식 가능한 코드를 작성할 때는이를 불투명 한 작업으로 처리해야합니다.
Linux x86-64에서는 va_list
변수에 대해 하나의 순회 만 수행 할 수 있습니다 . 더 많은 순회를 수행하려면 va_copy
먼저 사용하여 복사해야합니다 . man va_copy
세부 사항을 설명합니다 :
va_copy ()
명백한 구현은 va_list가 variadic 함수의 스택 프레임에 대한 포인터가 될 것입니다. 그러한 설정 (지금까지 가장 일반적인)에서는 과제에 반대하는 것이 없습니다.
va_list aq = ap;
불행히도 포인터 배열 (길이 1)을 만드는 시스템도 있습니다.
va_list aq; *aq = *ap;
마지막으로, 인수가 레지스터에 전달되는 시스템에서는 va_start ()가 메모리를 할당하고, 여기에 인수를 저장하고, 다음 인수를 표시하여 va_arg ()가 목록을 통과 할 수 있도록해야 할 수 있습니다. 이제 va_end ()는 할당 된 메모리를 다시 해제 할 수 있습니다. 이러한 상황을 수용하기 위해 C99는 va_copy () 매크로를 추가하여 위의 할당을 다음으로 대체 할 수 있습니다.
va_list aq; va_copy(aq, ap); ... va_end(aq);
va_copy ()의 각 호출은 동일한 함수에서 va_end ()의 해당 호출과 일치해야합니다. va_copy ()를 제공하지 않는 일부 시스템에는 제안 초안에 사용 된 이름이므로 대신 __va_copy가 있습니다.
일반적인 "스택에 전달 된 매개 변수"구현에서, 나는 va_end ()가 보통 아무것도 / 비어 있거나 / 널이라고 생각합니다. 그러나 전통적인 방식이 덜한 플랫폼에서는 필요합니다. 플랫폼 중립을 유지하기 위해 포함하는 것이 "좋은 관행"입니다.
'program story' 카테고리의 다른 글
Android에서 시스템 앱과 권한있는 앱의 차이점은 무엇입니까? (0) | 2020.12.31 |
---|---|
virtualenv를 이동할 수 있습니까? (0) | 2020.12.31 |
이미지가로드 된시기를 감지하는 브라우저 독립적 인 방법 (0) | 2020.12.31 |
PHP에서 finally 블록의 부족을 어떻게 해결할 수 있습니까? (0) | 2020.12.31 |
Haskell에서 .hs 파일을 가져 오는 방법 (0) | 2020.12.31 |