C 코딩 디자인-함수 포인터?


24

나는이 PIC18F46K22을 하고 XC8 컴파일러로 프로그램. 결국, 내가 가진 PC와 같은 시스템해야합니다 stdinstdout. 메인 루프에는 새로운 입력이 있는지 확인하는 기능이 있습니다. 입력이 있으면 그에 따라 함수가 호출됩니다. 예를 들어 A on을 입력 stdin하면 PIC는 B를 입력 할 때 호출되는 function_A대신 함수를 실행 function_B합니다.

PIC가 함수로 완료되면 새 입력이 함수로 전송되기를 원합니다. 따라서 A를 누르면 RS232 송신기가 열리고 그 순간부터 모든 입력이 RS232를 통해 전송됩니다. 결국 프로젝트는 독립형 텍스트 편집기입니다. 따라서 A를 누르면 파일 시스템이 열리고, 그 순간부터 텍스트 편집이 아닌 파일 목록을 살펴 봅니다. 즉, 위와 아래를 누르는 것은 텍스트 편집 환경과 다른 것을 의미합니다.

나는 이것을 C로 프로그래밍하는 방법에 대해 많은 생각을했다. 나는 지난 밤에 이것을 생각했고 그것이 가능하고 가능하다면 어떻게 알고 싶다. 내가하고 싶은 것은 :

  • main함수는 다음과 같은 함수를 호출합니다.function_A
  • function_A전역 변수 function_addr를 함수의 주소 포인터로 변경in_function_A
  • 그때부터 새로운 입력이있을 때 main함수를 호출합니다 function_addr.

그래서 필요한 것은 0 main인지 확인 하는 함수입니다 function_addr. 그렇다면 '정상적인'함수를 호출해야합니다 function_A. 그렇지 않으면 at 함수를 function_addr호출해야합니다. 또한를 포인터로 function_A변경 해야합니다 .function_addrin_function_A

참고 : 파일 시스템 기능을 닫아야 하는 경우 0으로 is_function_A변경해야합니다 function_addr.

기본적으로 내 질문은 어떻게

  • 함수의 주소를 가져 와서 변수에 저장
  • 지정된 주소에서 함수 호출

6
주제를 벗어. stackoverflow.com에 속합니다.
user207421

나에게 상태 머신 접근 방식은 함수 포인터를 다루는 것보다 훨씬 덜 위험합니다. 입력 바이트는 상태 변수 또는 함수에 따라 다양한 코드 비트로 이동하는 상태 머신 구조 (스위치 케이스처럼 간단 할 수 있음)로 전달됩니다. 또한 stdin이 어디에서 왔는지 완전히 명확하지 않습니다 (정말 중요하지는 않지만 궁금합니다).
Adam Lawrence

9
@EJP 동의하지 않습니다. 겹침이 있다고해서 한 사이트 또는 다른 사이트에 있어야한다는 의미는 아닙니다. 저수준 임베디드 시스템의 설계 및 프로그래밍과 관련하여 질문이 있습니다.
Kortuk

상태 머신은 함수 간접을 기반으로 할 수 있습니다. 상태 전이 함수에 대한 호출은 새로운 상태 전이 함수를 반환합니다.
Kaz

1
이 토론을 여기서 보자 .

답변:


21

기능

int f(int x){ .. }

함수의 주소를 가져 와서 변수에 저장

int (*fp)(int) = f;

지정된 주소에서 함수 호출

int x = (*fp)( 12 );

3
+1, C 및 ASM 세계에서는 명백하지만 OO 언어로 시작한 사람들에게는 그렇게 명확하지 않습니다.
Anindo Ghosh

4
fp 호출은 'int x = fp (12);'로 쓸 수도 있습니다. 가독성을 높이기 위해.
Rev1.0

1
나는 현재 C #과 Java에서 주로 일하고 있음을 인정해야하며 때로는 C의 좋은 오래된 함수 포인터를 그리워합니다. 정확하게 수행하지 않으면 위험하며 대부분의 작업은 다른 방식으로 수행 할 수 있지만 실제로 유용 할 때 몇 번 유용 합니다.
CVn

@ MichaelKjörling : 그렇습니다. 나는 임베디드 C와 C # 프로그래밍 사이에서 끊임없이 전환하고 있으며 (장치와 PC 간의 통신을 위해 유사한 코드를 구현하더라도) C #만큼 강력하지만 여전히 C를 많이 즐깁니다.
Rev1.0

2
fp(12)가독성을 향상시키지 않습니다 (*fp)(12). 가독성이 다릅니다. (*fp)(12)독자 fp에게 포인터 임을 상기시키고 의 선언과 유사합니다 fp. 내 생각에이 스타일은 X11 내부 및 K & R C와 같은 오래된 소스와 연관되어 있습니다. K & R C와 연관 될 수있는 한 가지 이유는 ANSI C에서는 매개 변수 fp인 경우 함수 구문을 사용하여 선언 할 수 있기 때문입니다 fp. int func(int fp(double)) {}. K & R C에서 그랬을 것 int func(fp) int (*fp)(double); { ... }입니다.
Kaz

17

Wouters의 답변 은 절대적으로 정확 하지만 초보자에게 친숙하고 질문에 대한 더 나은 예일 수 있습니다.

int (*fp)(int) = NULL;

int FunctionA(int x){ 
    return x + x;
}

int FunctionB(int x){ 
    return x * x;
}

void Example(void) {
    int x = 0;

    fp = FunctionA;
    x = fp(3);  /* after this, x == 6 */

    fp = FunctionB;
    x = fp(3);  /* after this, x == 9 */
}

함수 포인터에 실제로 대상 함수 주소가 할당되어 있는지 확실하지 않은 경우 NULL 검사를 수행하는 것이 좋습니다.

if (fp != NULL)
    fp(); /* with parameters, if applicable */

8
널 검사의 경우 +1 이지만 , 컴파일러가 fp차지하는 RAM 주소의 값 이 실제로 초기에 NULL 임을 보장하지는 않습니다 . 나는 int (*fp)(int) = NULL;선언과 초기화를 결합하여 확실하게 수행 할 것입니다-당신은 방금 일어났던 구피 값 때문에 임의의 메모리 위치로 이동하고 싶지 않습니다. 그런 다음 함수 fp에서처럼 지정 하십시오 Example().
CVn

1
의견 주셔서 감사합니다, 나는 NULL 초기화를 추가했습니다.
Rev1.0

4
@ MichaelKjörling은 좋은 점이지만 fp"전역 변수"(위의 코드에서와 같이) 인 경우 NULL(명확하게하지 않아도) 초기화됩니다 .
Alok
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.