C 함수의 인수와 C 함수의 오버로드에 대한 기본값
C++ lib를 ANSIC로 변환하는데 ANSIC가 함수 변수에 대한 기본값을 지원하지 않는 것 같습니까? 아니면 제가 잘못 알고 있는 것입니까?제가 원하는 것은 이런 것입니다.
int funcName(int foo, bar* = NULL);
또한 ANSIC에서 기능 과부하가 가능합니까?
필요합니다.
const char* foo_property(foo_t* /* this */, int /* property_number*/);
const char* foo_property(foo_t* /* this */, const char* /* key */, int /* iter */);
물론 이름을 다르게 지정할 수는 있지만 C++에 익숙해진 저는 오버로드 기능을 하곤 했습니다.
아니요, 표준 C도 지원하지 않습니다.C++ 코드를 C로 변환해야 한다고 생각하는 이유는 무엇입니까?상당히 까다로워질 수도 있습니다. C++에서 C++를 호출할 수 있어야 한다면 포장지를 작성하는 것이 좋은 방법이라고 생각했을 것입니다.
그럼에도 불구하고 GCC(2020년 12월 편집) 또는 C++2a와 호환되는 컴파일러를 사용하면 "트릭"을 찾았습니다. 예, 컴파일 전 트릭이기 때문에 '플레인 C'와 함께 작동합니다.
GCC에는 가변 매크로에서 기본 인수를 시뮬레이션할 수 있는 편리한 ## 확장자가 있습니다.
트릭에는 한계가 있습니다. 기본값 1개에 대해서만 작동하며 인수는 함수 매개 변수 중 마지막에 해당해야 합니다.
여기 작동 예가 있습니다.
#include <stdio.h>
#define SUM(a,...) sum( a, (5, ##__VA_ARGS__) )
int sum (a, b)
int a;
int b;
{
return a + b;
}
main()
{
printf("%d\n", SUM( 3, 7 ) );
printf("%d\n", SUM( 3 ) );
}
이 경우 SUM을 기본 두 번째 인수를 5로 합하는 호출로 정의합니다.
만약 당신이 2개의 인수를 가지고 전화를 걸면(첫 번째로 메인으로 전화를 걸면), 그것은 sum(3, (5, 7))으로 전처리 될 것입니다;
이것은 다음을 의미합니다.
- 첫번째 주장은 3입니다.
- 두번째 인수는 수열 (5, 7)의 결과입니다..당연히 7!
gcc가 영리하기 때문에, 이것은 시퀀스의 첫 번째 멤버가 상수이고 필요하지 않기 때문에 런타임에 영향을 미치지 않습니다. 컴파일 시에 단순히 폐기될 것입니다.
단 하나의 인수로 호출하는 경우, gcc 확장자는 VA_ARGS와 선행 코마를 제거합니다.따라서 다음과 같이 전처리됩니다.
합계( 3, (5 );
따라서 프로그램은 다음과 같은 예상 출력을 제공합니다.
10
8
따라서 2개의 인수가 있는 함수를 완벽하게 시뮬레이션합니다(일반적인 매크로 제한으로). 마지막 인수는 기본값이 적용되지 않는 선택사항입니다.
편집
-a) CLANG(및 다른 컴파일러)에서도 작동합니다.
-b) 사용되지 않는 인수에 대해 불평하지 않는 버전:
#define DEF_OR_ARG(z,a,arg,...) arg
#define SUM(a,...) sum( a, DEF_OR_ARG(,##__VA_ARGS__,__VA_ARGS__,5))
[편집 - 2020년 10월] : 새로운 것도 시도해 볼 수 있습니다__VA_OPT__
gcc 확장자인 ## 대신 c++2a로 표준화(그리고 일반 C에서도 작동해야 함)되었습니다.일반적인 용도는__VA_OPT__(,)
논제 목록이 비어 있지 않을 때 혼수상태가 추가되고 그렇지 않으면 아무것도 출력되지 않습니다.
[편집 - 2020년 12월] : 위의 트릭을 사용하여__VA_OPT__
, 다음이 됩니다.
#define DEF_OR_ARG(value,...) value
#define SUM(a,...) sum( a, DEF_OR_ARG(__VA_ARGS__ __VA_OPT__(,) 5))
사용하지 않는 변수에 대해 불만을 제기할 수 있는 '시퀀스 트릭'과 달리, 이것은 사전 컴파일러만 포함하고 판독성이 더 높습니다.
하나의 인수만으로 SUM을 호출하면,...
비어있고.__VA_OPT__
아무것도 출력하지 않습니다.DEF_OR_ARG(__VA_ARGS__ __VA_OPT(,) 5)
된다DEF_OR_ARG( 5)
SUM이 두 번째 인수와 함께 호출되면,...
이것이 두번째 논쟁이고.__VA_OPT__
혼수상태에 해당하는 값으로 확장됩니다.그 경우에는DEF_OR_ARG(__VA_ARGS__ __VA_OPT(,) 5)
된다DEF_OR_ARG(second_argument_of_SUM , 5)
이제 확장은DEF_OR_ARG
일어난다. 첫 번째 주장만 고려하고 나머지는 버리기 때문에 쉽습니다.이것은 첫 번째 주장만 고려하고 나머지는 버리기 때문에 쉽습니다.그래서 언제.SUM
두 번째 주장(위의 첫 번째 사례) 없이 호출되었으며, 첫 번째 주장은 다음과 같습니다.DEF_OR_ARG
기본값입니다.그 사건에서 두번째 논쟁이 있었습니다.SUM
, 할 첫번째 주장이 됩니다.DEF_OR_ARG
그것으로 확장되고 이제 두 번째 인수인 기본값을 폐기합니다.
이거 먹어봐요.
#include <stdio.h>
#include <stdarg.h>
/* print all non-negative args one at a time;
all args are assumed to be of int type */
void printargs(int arg1, ...)
{
va_list ap;
int i;
va_start(ap, arg1);
for (i = arg1; i >= 0; i = va_arg(ap, int))
printf("%d ", i);
va_end(ap);
putchar('\n');
}
int main(void)
{
printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);
printargs(84, 51, -1);
printargs(-1);
printargs(1, -1);
return
0;
}
필요한 기본 매개 변수 수만큼 지원할 수 있는 방법이 있습니다. 구조를 사용하기만 하면 됩니다.
// Populate structure with var list and set any default values
struct FooVars {
int int_Var1 = 1; // One is the default value
char char_Command[2] = {"+"};
float float_Var2 = 10.5;
};
struct FooVars MainStruct;
//...
// Switch out any values needed, leave the rest alone
MainStruct.float_Var2 = 22.8;
Myfunc(MainStruct); // Call the function which at this point will add 1 to 22.8.
//...
void Myfunc( struct FooVars *MyFoo ) {
switch(MyFoo.char_Command) {
case '+':
printf("Result is %i %c %f.1 = %f\n" MyFoo.int_Var1, MyFoo.char_Command, MyFoo.float_Var2, (MyFoo.float_Var2 + MyFoo.int_Var1);
break;
case '*':
// Insert multiply here, you get the point...
break;
case '//':
// Insert divide here...
break;
}
}
ANSIC가 함수 오버로드나 기본 인수를 직접 지원하지 않는 것으로 알고 있습니다.오버로드에 대한 표준 대용품은 인수 유형을 나타내는 함수 이름에 접미사를 추가하는 것입니다.예를 들어, OpenGL에서 함수 이름에 "3fv" 접미사를 붙이면 함수는 3개의 부동소수점 벡터를 사용합니다.
기본 인수는 함수 오버로드의 특수한 경우로 볼 수 있습니다.
ANSIC에는 기본값이나 함수 오버로드가 존재하지 않으므로 다른 방법으로 해결해야 합니다.
C가 그들을 지원하지 않기 때문에 그렇게 쉽게 할 수 없습니다."가짜 과부하"를 얻는 더 간단한 방법은 이미 말했듯이 접미사를 사용하는 것입니다.기본값은 변수 인수 함수를 사용하여 시뮬레이션할 수 있으며 전달된 아르그 수를 지정하고 누락된 아르그 수에 대한 기본값을 프로그래밍 방식으로 제공할 수 있습니다.
aType aFunction(int nargs, ...)
{
// "initialization" code and vars
switch(nargs)
{
case 0:
// all to default values... e.g.
aVar1 = 5; // ...
break;
case 1:
aVar1 = va_arg(arglist, int); //...
// initialize aVar2, 3, ... to defaults...
break;
// ...
}
}
추가하고 전달할 추가 정보가 있는 변수를 사용하여 오버로드를 시뮬레이션할 수도 있습니다.기본적으로 미니멀리스트 객체 지향 런타임을 재현합니다.다른 솔루션(또는 실제로 동일하지만 접근 방식이 다른)은 태그를 사용할 수 있습니다. 각 인수는 쌍 인수 유형 + 인수(가능한 인수 유형의 전체 집합에서 결합), 특수 터미네이터 태그(통과하는 아르그 수를 지정할 필요가 없음), 물론 항상 자신이 ca인 함수의 "협업"이 필요합니다.lling, 즉 태그를 구문 분석하고 수행할 실제 함수를 선택하기 위해 추가 코드를 포함해야 합니다(이것은 일종의 디스패처처럼 동작합니다).
C는 이름 망글링을 하지 않기 때문에 C에서 각각의 C++ 과부하 함수를 다르게 선언해야 할 것입니다."foo_property1" "foo_property2"의 경우.
변수 인수로 함수를 사용할 수 있다고 생각합니다. 여기 제 예시가 있습니다.
#include <stdarg.h>
#include <stdio.h>
void baz( int flag, ... )
{
va_list ap;
char *bar = "baz"; /* default value */
va_start( ap, flag );
if ( flag == 1 )
bar = va_arg( ap, char * );
va_end( ap );
printf( "%s\n", bar );
}
int main( void )
{
baz( 0 );
baz( 1, "foo");
baz( 2 );
baz( 1, "bar");
return 0;
}
산출량은
baz
foo
baz
bar
만약 당신이 열려있는 예제맨2를 찾는다면 그들은 말합니다.
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
int openat(int dirfd, const char *pathname, int flags);
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
하지만 모드는 사실... 논쟁입니다.
언급URL : https://stackoverflow.com/questions/2988038/default-values-on-arguments-in-c-functions-and-function-overloading-in-c
'source' 카테고리의 다른 글
Linux 정적 라이브러리에서 기호 제한 (0) | 2023.10.23 |
---|---|
DB 업데이트 후 수동으로 최대 절전 모드 2단계 캐시 지우기 (0) | 2023.10.23 |
VS 2012에서 웹 배포 게시 작업 전에만 PowerShell 스크립트를 실행하는 방법은 무엇입니까? (0) | 2023.10.23 |
Android ClickableSpan이 Click을 호출하지 않음 (0) | 2023.10.23 |
jQuery 객체 및 DOM 요소 (0) | 2023.10.23 |