2011-12-25 5 views
1

double (*)(double)double(*)(...)으로 전송하는 것이 안전한지 궁금합니다. 여러 기능을 가리키는 코드를 일반화하는 데 사용됩니다.C++ : 함수 포인터를 사용하는 것이 안전합니까?

지금까지 벡터에서 함수로 전달 될 모든 것을 저장했습니다. 함수에서 올바른 수의 인수를 전달하면서 함수를 호출하는 방법이 있는지 궁금합니다. 일반화 된 코드? 뭔가이 의미 :

//while initializing 
mFunction = sin; 
//later in code 
double (*generalized)(...) = mFunction; 
for(i=0;i<args.size();i++) 
    pusharg(args[i]); 
call(generalized); 

--edit--

saftly 어셈블리를 사용하여 함수를 호출하는 것이 가능하다 C++를 사용하여 할 수있는 유효한 방법이없는 경우?

+0

음, 그렇지 않습니다! 나는 "함수 포인터"에서 "다른 포인터와 함수 포인터"로 캐스팅하려고합니다. "void *"를 "함수 포인터"에 캐스팅하려고 시도합니다. – Ali1S232

답변

3

double(*)(double)double(*)(...)에 직접 할당 할 수는 없지만 reinterpret_cast 수 있습니다. 캐스팅 명시 적/6 §5.2.10 [expr.reinterpret.cast 의해 허용되지만, 주조 된 기능 포인터를 호출하는 단계 정의되지 않은 동작이 발생할 것이다

포인터 명시 함수 포인터로 변환 될 수있는 함수 다른 유형의

함수의 정의에서 사용 된 유형과 다른 함수 유형에 대한 포인터를 통해 함수를 호출 할 때의 결과는 이며 정의되지 않음은입니다.

원래의 형태로 되돌아 (T1T2 함수 타입이다) "T2 포인터"형태로 "T1 포인터 '유형의 prvalue를 변환하면 원래 포인터 값의 결과를 산출한다는 점을 제외하고 이러한 포인터 변환은 지정되지 않습니다.

UB로가는 이유를 쉽게 알 수 있습니다. generalized(1.0, 2.0, 3.0)으로 전화하면 어떻게 될까요? 그러면 호출 스택이 손상 될 수 있습니다. 그러나 전화하기 전에 generalizeddouble(*)(double)으로 다시 캐스팅하면 문제가 없습니다.

+0

개인 멤버이므로이 태그는 아닙니다. 가능한 프로그래머 실수에 대해 걱정할 필요가있다. 그래서'sin (double)'을'generalize (double, ...) '로 변환하면'generalize (1.0)'만 호출하거나'hypot (double, double)'이라면 반드시 호출 할 것입니다. 'generalize (1.0,2.0)' – Ali1S232

+0

@Gajet : 가능한 경우 오류를 피하기 위해 원래 유형으로 다시 캐스트하는 것이 좋습니다. '...'는 호출 규칙을 바꿀 수 있습니다 (예를 들어'float'을'...'인자에 넘겨 주면 함수를 호출하기 전에'double'으로 변환됩니다). – kennytm

1

예, 전송 자체는 허용됩니다. 그러나 잘못된 서명으로 호출하는 것은 아닙니다. 제네릭 함수 포인터를 원한다면 void (*)()을 더 잘 사용하십시오. 함수 포인터는 void*과 같습니다 (암시 적으로 변환하지는 않습니다).

더 나은 것은 특정 인수를 apperently 제공하기 때문에 std::functionstd::bind (컴파일러가 C++ 11 라이브러리를 지원하는 경우) 또는 Boost 해당 항목을 사용하는 것입니다.

+0

" 'void (*) (boost :: noncopyable)'와 같이 호출 할 수없는 포인터를 사용하고 싶습니다. – curiousguy

+0

거기에는 나를위한 트릭을 수행하는 동등한 어셈블리 코드가 있습니까? – Ali1S232

+0

@ 가젯 : 아시다시피 조립은 대단히 어렵습니다. 그것은 가능할 것이다. 호출 코드가 기본적으로 몇 가지 어셈블리 라인이되기 때문에 자체 위임 클래스를 구현했습니다. 그러나 매우 버그가있어 문제를 일으킬 수 있습니다. – Xeo

0

generalized을 volatile로 만들려면 컴파일러에서 ABI 사양을 따라야합니다. 선언되지 않은 C 함수를 지원하려는 욕구로 인해 고정 인수 수를 사용하여 함수에 대한 포인터를 사용하여 가변 개수의 인수를 제외한 함수를 호출하지 않으면 대부분의 ABI (x86 및 x86-32 포함)에서 안전합니다. .

관련 문제