Skip to content

Latest commit

 

History

History
128 lines (90 loc) · 3.95 KB

函数指针与可变参数.md

File metadata and controls

128 lines (90 loc) · 3.95 KB

C语言 函数指针 与 C++的可变参数

在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量称为"函数指针变量"。

函数指针变量定义的一般形式为:

类型说明符 (*指针变量名)();

其中 "类型说明符"表示被指函数的返回值的类型。"(* 指针变量名)" 表示 "*" 后面的变量是定义的指针变量。最后的空括号表示指针所指的是一个函数。例如:

int (*pf) ();

表示pf是一个指向函数入口的指针变量,该函数的返回值(函数值)是整型。

本例用来说明用指针形式实现对函数调用的方法。

int max(int a,int b){
    if(a>b)return a;
    else return b;
}
main(){
    int max(int a,int b);
    int(*pmax)();
    int x,y,z;
    pmax=max;
    printf("input two numbers:\n");
    scanf("%d%d",&x,&y);
    z=(*pmax)(x,y);
    printf("maxmum=%d",z);
}

从上述程序可以看出用,函数指针变量形式调用函数的步骤如下:

  1. 先定义函数指针变量,如后一程序中第9行 int (*pmax)(); 定义 pmax为函数指针变量。
  2. 把被调函数的入口地址(函数名)赋予该函数指针变量,如程序中第11行 pmax=max;
  3. 用函数指针变量形式调用函数,如程序第14行 z=(*pmax)(x,y);
  4. 调用函数的一般形式为:(*指针变量名) (实参表)

在C++中使用函数指针需要指明 函数指针的参数类型(?)

int max2Num(int a,int b){
    return (a >= b)?a:b;
}
main(){
   
    int num1 = 2,num2 = 3,num3 = 4;
//    int max2Num(int a,int b);
    int (*pmax)(int,int);
    pmax = max2Num;
    int r1 = (*pmax)(num1,num2);
    std::cout<<r1<<std::endl;
}

在C++中使用可变参数

在C++11之前,可以通过C语言的方式实现可变参数函数。

在C++11之后,可以通过std::initializer_list或参数包来实现。

std::initializer_list只能实现参数数目可变,但这些参数必须具有相同的类型(或者它们的类型可以转换为同一个公共类型)。而通过参数包,可以实现参数数目和类型都可变。

使用函数指针变量还应注意以下两点:

std::initializer_list是一个类模板,可以通过初始化列表来构造它。

简单示例

#include <initializer_list>
#include <iostream>

template <typename Ty>
Ty add_nums(std::initializer_list<Ty> il) {
    std::cout << "count: " << il.size() << "\n";

    int sum = 0;

    for (auto it = il.begin(); it != il.end(); ++it) {
        sum += *it;
    }

    return sum;
}

int main() {
    //类型推断
    std::cout << add_nums({25, 25, 50, 50}) << "\n";
}

需要注明类型的示例

#include <initializer_list>
#include <iostream>

template<typename Ty>
Ty maxN(Ty a,std::initializer_list<Ty> il){
    Ty maxNum = a;
    for(auto it = il.begin();it != il.end();it++)
        maxNum = (maxNum >= *it)?maxNum:*it;
    return maxNum;
}

int main(){
    int a = 5;
    int res = maxN<int>(a,{2,3,4,100});
    //对于空的{} 需要注明类型 这里由于 (Ty a,std::initializer_list<Ty> il)类型一致可以省略
    //如果参数类型为这样 (int a,std::initializer_list<Ty> il),则空的{} 必须要注明类型否则编译不通过
    int res = maxN<int>(a,{});
    std::cout<<"可变参数返回结果:"<<res<<std::endl;
}

使用函数指针变量还应注意以下两点:

  • 函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。
  • 函数调用中"(* 指针变量名)"的两边的括号不可少,其中的*不应该理解为求值运算,在此处它只是一种表示符号。