2010-08-15 6 views
6

함수 내에서 정적으로 선언 된 변수를 재설정하는 방법이 있습니까? 목표는 비 관련 호출에서 느린 값으로 함수가 호출되지 않도록하는 것입니다. 예를 들어, 행렬의 열에 함수가 있습니다.함수 내에서 정적 변수를 재설정하는 방법

int foo(matrix *A, int colnum, int rownum){ 
static int whichColumn; 
static int *v; //vector of length A->nrows 
    if (column != whichColumn){ 
    memset(v,0,size); 
    whichColumn = which; 
    } 
    //do other things 
} 

이 함수는 각 열에 대해 한 번 n 번 호출됩니다. 이것은 정적 변수를 "다시 설정"하는 올바른 방법입니까? 정적 변수를 재설정하는 다른 일반적인 바보 같은 방법이 있습니까? 예를 들어, 가능한 경우 다른 치수를 가진 새 행렬을 호출하면 vector v의 크기가 조정되고 0이됩니다. 가장 쉬운 방법은 NULL 포인터를 사용하여 함수를 호출하는 것입니다.

int foo(matrix *A, int colnum, int rownum){ 
static int whichColumn; 
static int *v; //vector of length A->nrows 
    if (A == NULL){ 
    FREE(v); 
    whichColumn = 0; 
    } 
    //do other things 
} 
+2

정적/전역 변수를 사용하지 마십시오. 대신 호출자가 호출간에 상태를 보존하기 위해 유지 보수하는 정수에 대한 포인터를 함수에 전달하십시오. –

+0

방금 ​​정적 변수를 재설정해야하지만 테스트 코드에서만 다시 비슷한 문제가 발생했습니다. 내 해킹은 입력 포인터를 NULL로 설정하고, func에서 그 값을 확인한 다음, 적절하게 변수를 재설정하는 것이었다. 효과적으로 기존 매개 변수에서 NULL 값을 플래그로 사용했다. 약간 냄새가 나지만 작동합니다. – bph

+0

정적 멤버 변수를 가진 클래스가 아마도 이상적인 솔루션이 될 것입니다. 그러나 C (OOP가 없음)를 사용하면 정적 구조체가 아마도 가장 우아한 솔루션 일 것입니다. – bph

답변

0

구조체로 변환하고 수행하려는 작업의 의미를 관리하기위한 작은 도우미 함수를 작성하는 것이 좋습니다. 요청이 크기에 적합한 경우 버퍼를 반환하거나 요청에 따라 새 버퍼를 만들고 필요하면 이전 버퍼를 비울 수 있습니다.

+1

래퍼 클래스를 작성 하시겠습니까? C에서? – Beta

+0

어쨌든 struct + helper 함수는 어떨까요? –

+0

감사합니다. Jesse, Borealid에 대한 내 의견을 통해 teo 접근 방식의 하이브리드를 사용했습니다. "재설정"기능을 사용하여 외부 세부 정보를 숨길 수 있습니다. 나는 C++을 모른다. 그래서 래퍼 클래스는 ootq이다. – Sue

3

멱등수 이니셜 라이저 함수와 전역 변수를 대신 사용하십시오. 예를 들어

:

int foo; 
int *m = NULL; 

static void InitVars() { 
    foo = 0; 
    if (m != NULL) { 
     free(m); 
    } 
    m = malloc(sizeof(int)*5); 
    memset(m, 0, sizeof(int)*5); 
} 

당신의 초기화가 정말 나무 등입니다 경우, 변수를 재설정 다시 호출 할 수 있습니다. 이 자동적으로 호출하는 경우 필요

,과 같이 __attribute__((constructor)) (GCC를 위해) 사용 : 그러나

static void InitVars __attribute__((constructor))(); 

, 당신은이 작업을 수행해야하는 경우, 당신은 인 - 사용 재고해야 있음을 유의 function static 변수를 사용하고 반환 된/쓰여지고 후속 관련 호출에 전달 된 전달 된 새 값을 대신 사용합니다.

+0

안녕하세요. 나는 조언을 따르고 * v를 정적 변수로 사용하지 않기로 결정했다. 대신에 whichColumn을 statitc 변수로 사용했다. v 이제 Jesse가 권장하는 구조체의 일부입니다. passing (column = -1)은 통계 변수를 재설정하고 작업 벡터를 다시 활성화합니다. 그런 다음 각 시간에 대해 적절하게 업데이트됩니다 (column! = whichColumn). 다른 제안은 유용하게 들리지만 나는 그것에 대해 배울 것입니다. 다시 한번 감사드립니다. sm – Sue

+0

흠 - 조금 위험 해 보입니다. 전역 변수가있는 가장 강력한 솔루션이 주위에 걸려 있는지 확실하지 않습니다. – bph

0

C 모듈을 C++로 가져올 때 사용한 한 가지 접근 방법은 전체 래퍼로 모듈을 둘러싸고 함수 내부의 모든 정적 변수를 함수 외부의 고유 한 전역 변수로 바꾸는 것입니다. 하나의 파일이 있는지 알고 싶지만 여러 소스 파일과 관련된 프로젝트에서 비슷한 효과를 얻을 수있는 좋은 방법을 모르겠습니다. C에서 일부 임베디드 시스템 코드가 있는데 VS2005에서 C++ 래퍼를 추가하여 시뮬레이션합니다. 예를 들어, I/O 레지스터는 TX1CON = 0x5C와 같은 것으로 정의되어 있습니다. IOMAP (0x251) .P = 0x5C; IOMAP은 "0x25C에 주소 0x251 쓰기"를 하드웨어 시뮬레이션 프로그램에 보내는 속성입니다. 이 방법은 잘 작동하지만 클린 재설정을 수행 할 수는 없습니다. 어떤 아이디어?

+0

이것으로 문제가 생기면 더 많은 함수가 추가됩니다. 게다가 당신은 궁극적으로 당신을 '신'기능의 안티 패턴으로 인도하는 사다리 위로 책임을 떠 밀고 있습니다. 나는 비 OOP 언어에 대해 명백한 '깨끗한'해결책이 있다고 생각하지 않는다. – bph

+0

@Hiett : VS2005의 C++ 래퍼로 설명 된 특정 시나리오에서 코드 팽창은 시뮬레이션 컨텍스트에서만 발생했다. 실제 시스템에는 128K ROM과 4K RAM이 있었으며 시뮬레이션 환경에는 RAM이 있었기 때문에 실제 시스템은 시뮬레이션 환경의 1 % 미만의 "원시 코드"를 실행했을 가능성이 높기 때문에 걱정거리는 시뮬레이션 환경에서의 효율성 여부와 관계없이 실제 시스템에서 효율적 이기만하면됩니다. 다른 상황에는 다른 요구 사항이 있습니다. – supercat

0

알 수없는 함수 또는 모듈에 도달 할 수있는 "재설정"방법이 필요한 경우 때때로 도움이 될 수있는 방법은 재설정 방법이 호출 된 횟수를 나타내는 전역 카운터를 갖는 것입니다. 정적 변수의 초기화의 일부 글로벌 변수에 따라 좌우 될 수 있다면 어떤 멀티 스레딩 맥락

 
extern unsigned long global_reset_count; 

void do_something(int whatever) 
{ 
    static ... this, that, the other, etc. ...; 
    static unsigned long my_reset_count; 

    if (my_reset_count != global_reset_count) 
    { 
    my_reset_count = global_reset_count; 
    ... initialize this, that, the other, etc ... 
    } 
} 

, 하나는 "동안"와 "경우"를 대체하고자 할 수있다 : 함수 또는 모듈 코드처럼 포함 몇몇 경우; 이러한 요구 사항은 운영 환경에 따라 달라질 수 있지만 메모리 장벽이 필요할 수도 있습니다.또한

, 글로벌 리셋 방법으로 0으로 설정 가져옵니다 modules_initialized 전역 변수를 가지고하는 것입니다 임베디드 시스템 내에서 유용, 다음과 같이 각 모듈의 시작을 가질 수있는 다른 패턴 :

 
    if (!atomic_bit_test_and_set32(&modules_initialized, FOOBOZZ_MODULE_ID)) 
    { 
    ... Initialize module FOOBOZZ ... 
    } 

이렇게하면 32 개 이상의 모듈 ID가 필요하며 어떤 식 으로든 고유하게 할당해야 할 수도 있지만 일부 시스템에서는이를 능숙하게 처리 할 수 ​​있습니다. 예를 들어, 링커는 다른 것과 독립적 인 주소 공간의 주소 0-31에서 "데이터 섹션"을 정의 할 수 있습니다. 각 모듈이 해당 주소 공간에서 싱글 바이트 변수를 선언하면 링커는 해당 변수에 대해 적절한 주소를 생성 할 수 있습니다.

int foo(matrix *A = NULL, int colnum = 0, int rownum = 0) 
{ 
    static int whichColumn; 
    static int *v; //vector of length A->nrows 

    if (A == NULL){ 
    FREE(v); 
    whichColumn = 0; 
    } 
    //do other things 
} 

당신은 실제로 단지가 :

당신이 제로 매개 변수를 호출하는 경우, 다음은 내부 정적 변수 여기

를 재설정하는 방식으로 함수를 만들 수
0

은 예입니다

foo(); // internal values would then be reset 

함수에 대한 모든 매개 변수에 기본값이 있어야합니다. 예를 들어 선택 사항 인 다음에 ma를 전달하면 그 부울은 기본값 = boost :: none을 가지고 있는지 확인하십시오.

관련 문제