C 언어 프로 그래 밍 의 함수 포인터 와 함수 리 셋 을 상세 하 게 설명 합 니 다.
함수 주 소 를 저장 하 는 지침 입 니 다.함 수 를 가리 키 는 지침 입 니 다.지침 에 저 장 된 값 은 함수 주소 입 니 다.우 리 는 지침 을 통 해 함 수 를 호출 할 수 있 습 니 다.
우 리 는 먼저 간단 한 함 수 를 정의 합 니 다.
//
void easyFunc()
{
printf("I'm a easy Function
");
}
//
void easyFunc();
//
easyFunc();
//
void easyFunc()
{
printf("I'm a easy Function
");
}
//
void easyFunc();
//
easyFunc();
위의 세 단 계 는 우리 가 함 수 를 배 울 때 반드시 해 야 하 는 것 이다.상기 세 단 계 를 통 해 우 리 는 완전한 함 수 를 정의 한 것 이다.어떻게 함수 지침 을 정의 합 니까?앞에서 우리 가 정의 한 다른 종류의 포인터 의 형식 은 형식*포인터 이름=하나의 주소 입 니 다.예 를 들 어:
int *p = &a;// p
즉,우리 가 어떤 종류의 지침 을 정의 하려 면 어떤 유형 을 알 아야 한다 면 함수 의 유형 은 어떻게 확정 합 니까?함수 의 유형 은 함수 의 성명 입 니 다.함수 이름 을 없 애 면 됩 니 다.예 를 들 어 위의 함수 의 유형 은:
void ()
인자 와 반환 값 이 있 는 함 수 를 다시 설명 합 니 다.
int add(int a, int b);
위의 함수 의 유형 은 여전히 함수 이름 을 없 애 면 됩 니 다.
int (int a, int b)
함수 의 유형 을 알 게 된 이상 함수 포인터 의 유형 은 바로 뒤에*를 추가 하면 됩 니 다.그렇지 않 습 니까?
int (int a, int b) * //
위 에서 이렇게 정의 한 것 은 잘못된 것 이다.절대적 으로 잘못된 것 이다.많은 초보 자 들 이 이렇게 한다.항상 이렇게 해 야 한다 고 생각한다.사실은 함수 포인터 의 유형 에 대한 정 의 는 비교적 특수 하 다.이것 은 다음 과 같다.
int (*) (int a, int b);// ,
int (*) (int a, int b);// ,
함수 포인터 가*뒤에 포인터 이름 만 추가 하면 됩 니 다.바로 아래 와 같 습 니 다.
int (*p)(int a, int b) = NULL;// NULL
int (*p)(int a, int b) = NULL;// NULL
만약 우리 가 p 에 값 을 부여 하려 고 한다 면,우 리 는 반환 값 형식 을 int 로 정의 해 야 합 니 다.두 매개 변 수 는 int 의 함수 입 니 다.
int add(int a, int b)
{
return a + b;
}
p = add;//
int add(int a, int b)
{
return a + b;
}
p = add;//
위의 할당 을 통 해 우 리 는 p 를 사용 하여 함 수 를 대표 할 수 있 습 니 다.
p(5, 6);// add(5, 6);
printf("%d
", p(5, b));
p(5, 6);// add(5, 6);
printf("%d
", p(5, b));
출력 결과:11위의 지침 함 수 를 통 해 함 수 를 사용 합 니 다.일반적으로 함수 의 주요 용법 이 아 닙 니 다.우 리 는 함수 지침 을 사용 하여 함수 의 반전 을 실현 하고 함 수 를 매개 변수 로 사용 합 니 다.
함수 포인터 값
함수 포인터 도 일반 포인터 와 마찬가지 로 메모리 주소 입 니 다.이 주 소 는 함수 의 시작 주소 일 뿐 입 니 다.아래 프로그램 은 함수 포인터 의 값(func 1.c)을 인쇄 합 니 다.
#include <stdio.h>
typedef int (*Func)(int);
int Double(int a)
{
return (a + a);
}
int main()
{
Func p = Double;
printf("%p
", p);
return 0;
}
컴 파일,실행 프로그램:
[lqy@localhost notlong]$ gcc -O2 -o func1 func1.c
[lqy@localhost notlong]$ ./func1
0x80483d0
[lqy@localhost notlong]$
그리고 우 리 는 nm 도구 로 Double 의 주 소 를 살 펴 보고 마침 0x 80483 d0 인지 아 닌 지 를 보 았 다.
[lqy@localhost notlong]$ nm func1 | sort
08048294 T _init
08048310 T _start
08048340 t __do_global_dtors_aux
080483a0 t frame_dummy
080483d0 T Double
080483e0 T main
...
뜻밖에도 Double 의 시작 주 소 는 역시 0x 080483 d0 이다.함수 반전
함수 리 셋 의 본질은 함수 바늘 을 함수 매개 변수 로 하고 함수 호출 시 함수 주소,즉 함수 이름 을 입력 하면 된다 는 것 이다.
우 리 는 언제 리 셋 함 수 를 사용 합 니까?우리 먼저 예 를 들 자.예 를 들 어 지금 샤 오 밍 이 숙제 를 못 하 는 문제 가 있어 서 샤 오 홍 에 게 전 화 를 걸 어'나 지금 숙제 를 못 하 는 문제 가 있 는데 네가 나 를 도와 해 줄 수 있 니?그리고 답 을 알려 주 시 겠 어 요?샤 오 홍 은 이 문 제 를 듣 고 바로 풀 수 있 는 문제 가 아니 라 고 생각 하여 샤 오 밍 에 게 내 가 다 하고 알려 주 겠 다 고 말 했다.이것 을 다 한 후에 샤 오 밍 에 게 함수 의 반전 이 라 고 알려 주 었 다.샤 오 밍 에 게 어떻게 알려 주 는 지,샤 오 홍 은 반드시 샤 오 밍 의 연락처 가 있어 야 한다.이 연락 처 는 바로 반전 함수 이다.다음 에 우 리 는 코드 로 실현 한다.
샤 오 밍 은 연락 처 를 샤 오 홍 에 게 남 겨 야 하고 답 도 얻어 야 하기 때문에 답 을 저장 할 수 있 는 매개 변수 가 필요 하 다.
void contactMethod(int answer)
{
//
printf(" :%d
", answer);
}
void contactMethod(int answer)
{
//
printf(" :%d
", answer);
}
, :
void tellXiaoMing(int xiaoHongAnswer, void (*p)(int))
{
p(xiaoHongAnswer);
}
// ,
tellXiaoMing(4, contactMethod);
void tellXiaoMing(int xiaoHongAnswer, void (*p)(int))
{
p(xiaoHongAnswer);
}
// ,
tellXiaoMing(4, contactMethod);
위의 반전 에서 왜 우리 가 직접 tellXiaoMing 방법 에서 contactMethod 함 수 를 호출 할 수 없 느 냐 고 물 을 것 이다.샤 오 홍 이 함수 지침 을 매개 변수 로 할 때 샤 오 밍 의 연락 처 를 저장 할 수 있 을 뿐만 아니 라 샤 오 밍 의 연락 처 를 저장 할 수 있 기 때문에 제 가 가지 고 있 는 코드 는 수정 하지 않 아 도 됩 니 다.당신 은 서로 다른 매개 변수 만 입력 하면 됩 니 다.그래서 이런 디자인 코드 는 실용성 이 높 고 유연성 이 큽 니 다.함수 리 턴 의 전체 과정 은 바로 위 와 같다.여기 서 중요 한 특징 은 우리 가 리 턴 을 사용 할 때 보통 한 가지 방법 으로 조작 을 기 다 려 야 할 때 사용 하 는 것 이다.예 를 들 어 위의 샤 오 홍 은 답 이 나 올 때 까지 기 다 려 야 샤 오 밍 에 게 알려 주 는 것 이다.샤 오 밍 이 샤 오 홍 에 게 물 었 을 때 샤 오 홍 이 가 직접 답 을 줄 수 있 으 면 리 턴 할 필요 가 없다.그러면 집행 순 서 는 다음 과 같다.
리 셋 순 서 는:
위 에 있 는 샤 오 홍 이 문 제 를 푸 는 것 은 기다 리 는 작업 이다.시간 이 걸 리 고 샤 오 밍 도 계속 전 화 를 들 고 기다 릴 수 없 기 때문에 샤 오 홍 이 가 문 제 를 풀 고 다시 전 화 를 걸 어야 샤 오 밍 에 게 답 을 알려 줄 수 있다.
따라서 함수 리 셋 은 두 가지 주요 특징 이 있다.
함수 포인터 가 매개 변수 로 서로 다른 함수 에 들 어 갈 수 있 기 때문에 서로 다른 함 수 를 되 돌 릴 수 있 습 니 다.
함수 리 셋 은 일반적으로 기다 리 거나 시간 이 걸 리 거나 일정 시간 또는 이벤트 가 발생 한 후에 리 셋 을 실행 해 야 하 는 상황 에서 사 용 됩 니 다.
우 리 는 함수 리 셋 을 사용 하여 동적 정렬 을 실현 합 니 다.우 리 는 현재 학생 의 구조 체 에 이름,나이,성적 을 포함 하고 있 습 니 다.우 리 는 학생 을 정렬 하 는 방법 이 있 습 니 다.그러나 구체 적 으로 이름 에 따라 배열 합 니까?아니면 나이 줄?아니면 성적 순위?이것 은 확실 하지 않 거나 잠시 후에 새로운 수요 가 있 을 수 있 기 때문에 동적 정렬 을 통 해 작성 한 후에 우 리 는 서로 다른 함수 만 입력 하면 된다.
학생 구조 체 정의:
// student, name,age score
struct student {
char name[255];
int age;
float score;
};
//typedef struct student Student
typedef struct student Student;
비교 결 과 를 정의 하 는 매 거 진:
//
enum CompareResult {
Student_Lager = 1, //1
Student_Same = 0,// 0
Student_Smaller = -1// -1
};
//typedef enum CompareResult StudentCompareResult
typedef enum CompareResult StudentCompareResult;
성적,연령,성적 비교 함수 정의:
/*
*/
StudentCompareResult compareByScore(Student st1, Student st2)
{
if (st1.score > st2.score) {// , 1
return Student_Lager;
}
else if (st1.score == st2.score) {// , 0
return Student_Same;
}
else { // , -1
return Student_Smaller;
}
}
/*
*/
StudentCompareResult compareByAge(Student st1, Student st2)
{
if (st1.age > st2.age) {// , 1
return Student_Lager;
}
else if (st1.age == st2.age) {// , 0
return Student_Same;
}
else {// , -1
return Student_Smaller;
}
}
/*
*/
StudentCompareResult compareByName(Student st1, Student st2)
{
if (strcmp(st1.name, st2.name) > 0) {// , 1
return Student_Lager;
}
else if (strcmp(st1.name, st2.name) == 0) {// , 0
return Student_Same;
}
else {// , -1
return Student_Smaller;
}
}
정의 정렬 함수:
/*
stu1[]:
count :
p : ,
*/
void sortStudent(Student stu[], int count, StudentCompareResult (*p)(Student st1, Student st2))
{
for (int i = 0; i < count - 1; i++) {
for (int j = 0; j < count - i - 1; j++) {
if (p(stu[j], stu[j + 1]) > 0) {
Student tempStu = stu[j];
stu[j] = stu[j + 1];
stu[j + 1] = tempStu;
}
}
}
}
구조 체 배열 정의:
//
Student st1 = {"lingxi", 24, 60.0};
Student st2 = {"blogs", 25, 70.0};
Student st3 = {"hello", 15, 100};
Student st4 = {"world", 45, 40.0};
// ,
Student sts[4] = {st1, st2, st3, st4};
출력 정렬 전 배열,정렬 및 정렬 후의 배열:
//
printf("
");
for (int i = 0; i < 4; i++) {
printf("name = %s
", sts[i].name);//
}
//
sortStudent(sts, 4, compareByName);
//
printf("
");
for (int i = 0; i < 4; i++) {
printf("name = %s
", sts[i].name);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C 언어 구현 천둥 제거 게임 상세 정보먼저 작은 메뉴를 표시하고 게임을 할지 여부를 선택하십시오.사용자가 종료를 선택하면 프로그램 실행이 끝나고, 사용자가 게임을 선택하면 지뢰 제거 위치 좌표를 입력하라는 메시지가 표시됩니다.사용자가 입력한 좌표가 바둑...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.