[C/C++]如何解读返回函数指针的函数声明

 

首先看下面main.c,test()和add()都未声明,但编译时不会报错

今天在看《深入理解C++11》的时候,看到一段有意思的代码:

1.如果有多个函数都是是在main函数前声明与定义的,那么main函数前的这几个函数要相互调用的话要注意顺序函数声明定义的位置

 1 #include<stdio.h> 
 2 
 3 //这是一个自定义函数,函数名为add,返回类型是int,有两个参数a、b 
 4 int add(int a, int b)   //函数名的第一个字符用字母或是下划线,不可用数字 
 5 {
 6     return a + b;
 7 }
 8 
 9 void test()    //定义一个函数没有返回值,没有参数 
10 {
11     printf("kun\n");
12 }
13 
14 void test1();   //函数的声明 
15 
16 int main()
17 {
18     int i = 8;
19     int j = 9;
20     int c = add(i, j);   //调用函数 
21     printf("%d + %d = %d\n", i, j, c);
22     test();
23     test1();   //调用一个没有参数的函数 
24     return 0;    
25 }
26 
27 void test1()
28 {
29     printf("world\n");
30 }

c里面 函数声明可以和函数定义(不同的c文件里面)

[html]
#include <stdio.h> 
 
void main() 
 

 
    printf(“%d\n”,test()); 
 

 
 
 
int test() 
 

 
    return add(1,2); 
 

 
 
 
int add(int x,int y) 
 

 
     return x+y; 
 

int (*(*pf())())() {
    return nullptr; 
}

2.为了解决上面的问题,最好是在main函数前声明,然后再在main函数后定义,这样main函数外的函数之间相互调用的就不需要注意顺序了,当然也可以分文件

 

可以返回不一样的类型

#include <stdio.h>

 

c++不可以 要求更严格

void main()

我立刻就懵了——从来没有见过这样的函数声明。那么它究竟是一个怎样的函数呢?我努力回忆起《C专家编程》一书的内容,把其中解读变量声明的方法应用于该函数上,最终读懂了该函数。下面是大致的解读过程。

原因是因为c的代码变量会被汇编成内存块,所以只有长度这一说法。与类型关系不大。

{

 

c++代码会先生成C代码。所以编译器检查更严格。

 printf(“%d\n”,test());

首先,要确定声明中出现的操作符的优先级。显然,函数调用操作符()的优先级是高于指针解引用操作符*的。另外,小括号总是具有最高优先级。

 

}

 

作者 RunBoying

 

其次,要确定在声明中标识符与某个操作符结合起来的时候有什么意义。例如:

函数声明可以和函数定义(不同的c文件里面)
可以返回不一样的类型 c++不可以 要求更严格
原因是因为c的代码变量会被汇编成内存块,…

int test()

a()    a是一个函数
*a     a是一个指针

{

由于函数声明的特殊性,当指针解引用操作符*与一个表示函数的标识符结合时,表示这个函数的返回值是一个指针。例如
*a() 表示a是一个返回值为指针的函数。

 return add(1,2);

 

}

有了以上的基础,接下来我们就可以从声明中的标识符开始,按照操作符的优先级,由内向外逐步来解读:

 

            pf()            pf是一个无参数函数
          * pf()            pf是一个无参数函数,它的返回值是一个指针
        ( * pf() ) ()       pf是一个无参数函数,它的返回值是一个无参数函数的指针
      * ( * pf() ) ()       pf是一个无参数函数,它的返回值是一个无参数函数的指针,这个函数的返回值又是一个指针
    ( * ( * pf() ) () ) ()  pf是一个无参数函数,它的返回值是一个无参数函数的指针,这个函数的返回值又是一个无参数函数的指针
int ( * ( * pf() ) () ) ()  pf是一个无参数函数,它的返回值是一个无参数函数的指针,这个函数的返回值又是一个无参数且返回值为int的函数的指针。

int add(int x,int y)

 

{

最终的解读结果冗长拗口。可以看出,这实际上是返回值为函数指针的函数的递归声明。下面是可读性更强的等效代码:

  return x+y;

typedef int (*pa)(); 
typedef pa (*pb)(); 
pb pfex() {  
    return nullptr; 
}

}

 

运行输出结果为:3

下面是验证解读结果的测试代码。不得不说,测试代码也不容易理解……

接着修改程序如下:

#include <iostream>

int a() {
    return 29; 
}

int (*b())() {
    return a; 
}

int (*(*pf())())() {
    return b; 
}

typedef int (*pa)(); 
typedef pa (*pb)(); 
pb pfex() {  
    return b; 
}

int wmain() {

    int r = pf()()();  
    std::wcout << r << std::endl;

    r = pfex()()();  
    std::wcout << r << std::endl;  
}

 

 

[html]
#include <stdio.h> 
 
void main() 
 

 
    printf(“%d\n”,test()); 
 

 
 
 
static int test() 
 

 
    return add(1,2); 
 

 
 
 
static int add(int x,int y) 
 

 
    return x+y; 
 

最终的输出是两个数字29。

#include <stdio.h>

void main()

{

 printf(“%d\n”,test());

}

 

static int test()

{

 return add(1,2);

}

 

static int add(int x,int y)

{

 return x+y;

}

编译时报错,提示test()和add()未声明。

为什么会这个样子呢,于是我又试着修改了一下程序:

[html]
#include <stdio.h> 
 
void main() 
 

 
    test(); 
 
 
 
void test() 
 

 
    //return add(1,2); 
    add(1,2); 
 

 
 
 
void add(int x,int y) 
 

 
    //return x+y; 
    x+y; 
 

#include <stdio.h>

void main()

{

 test();

 

void test()

{

 //return add(1,2);
 add(1,2);

}

 

void add(int x,int y)

{

 //return x+y;
 x+y;

}

 

这次报错了,注意了,和第一个例子相比只是将函数返回值不同而己!

接着先给出函数声明:

[html]
#include <stdio.h> 
 
void test(); 
void add(int x,int y); 
 
 
void main() 
 

 
    test(); 
 

 
 
 
void test() 
 

 
    //return add(1,2); 
    add(1,2); 
 

 
 
 
void add(int x,int y) 
 

 
    //return x+y; 
    x+y; 
 

#include <stdio.h>

void test();
void add(int x,int y);

void main()

{

 test();

}

 

void test()

{

 //return add(1,2);
 add(1,2);

}

 

void add(int x,int y)

{

 //return x+y;
 x+y;

}

编译顺利通过。

总结如下:

1.一般情况下,函数在调用子函数时,子函数必须先声明,要不会报错。(一般都将函数的声明放在一下头文件里)

2.如若子函数为返回值是int时,可不用声明,因为编译器会为子函数默认一个声明,返回值为int类型的,所以最开始的那个例子才不会报错。

3.static修饰的函数作用域为从声明/定义处到源文件结尾处为止。

 

[html] #include stdio.h void main() { printf(%d\n,test()); } int
test() { return add(1,2); } int add(i…

相关文章