第十九章、C 语言高级语法

本章我们来学习 C 语言中为了提高软件开发效率和运行效率等给出的一些语法规范。

1. 指针的类型总结

本节我们总结一下 C 语言中常用数据类型以及指向它们的指针的类型以及书写方法。

详见见如下表格

变量或函数
指向变量或函数的指针
说明
char c;
char *pc = &c;
pc 指向字符型数据
short s;
short *ps = &s;
ps 指向短整型数据
int i;
int *pi = &i;
pi 指向整型数据
long int l;
long int *pl = &l;
pl 指向长整型数据
long long int ll;
long long int *pll = ≪
pll 指向长长整型数据
float f;
float *pf = &f;
pf 指向浮点型数据
double d;
double *pd = &d;
pd 指向双精度浮点型数据
struct stu stu
struct stu * pstu
pstu 是指向 结构体的指针
union pkg g
union pkg *g
pg 是指向联合体的指针
enum color c
enum color *pc
pc 是指向枚举的指针
int *p;
int **pp = &p;
pp 是指向整型指针的二级指针
int a[100];
int(*pa)[100] = &a;
pa 是指向指向整型一维数组的指针
int ar[3][4];
int(*par)[3][4] = &ar;
par 是指向指向整型二维数组的指针
int* ap[100];
int*(*pap)[100] = ≈
pap是指向一维整型指针数组的指针
void fn(void);
void(*pfn)(void) = &fn;
pfn 是指向 void(void) 型函数的函数指针,表达式 &fn 等同于 fn
int fn(int x, int y);
int(*pfn)(int, int) = &fn;
pfn 是指向 int(int,int) 型函数的函数指针
void fn(int x, int(*fx)(float));
void(*pfn)(int, int(*)(float)) = &fn;
函数的参数是函数指针
int *fn(int x);
int *(*pfn)(int);
pfn 是指向返回值是指针的函数指针
void (*fn(int x))(int);
void (*(*pfn)(int))(int) = &fn;
返回值是函数指针函数的函数指针

最后一条看似很复杂,我们后面再解释。

上述我们分别声明了变量、数组和函数,也分别声明了指向变量、数组和函数的指针。此时你是否能否发现规律呢?

  1. 声明指向变量的指针在变量名处前加一个 * 然后把变量名改成指针名。
  2. 声明指向数组的指针在是将数组名用括号括起来,然后在数组名前加一个 * 然后把数组名改成指针名。
  3. 声明指向函数的指针在是将函数名用括号括起来,然后在函数名前加一个 * 然后把函数名改成指针名(函数的形参名可以去掉,也可以保持不变)。

上述指针在解引用后得到的就是指向的数据对象。类型也和指向的对象类型相同。

指针的运算

基本数组类型的指针、指针类型的指针和指向数组的指针可以进行运算加、减运算。函数指针通常不进行加、减运算。

  1. 基本数据类型的指针加 n 或减 n 则先前或向后移动一个n 个指向数据类型的长度。
  2. 指向数组的指针也是如此,如: 指针 int(*pa)[100],则 pa+1 则向后移动 400 个字节;指针 int(*par)[3][4],则 par+1 则向后移动 48 个字节。

函数指针的使用

函数指针可以(*函数指针)(实际调用参数)的方式解引用后调用,也可以使用 函数指针(实际调用参数) 的方式直接调用。

返回函数指针的函数

我们来看 void (*fn(int x))(int); 这个声明。这个是声明一个函数 fn(int x), 它有一个 形参变量 x,该函数返回值是一个 void(*)(int) 类型的函数指针。即该函数 fn 能够返回一个函数的地址。

如果想让返回函数指针的函数 写起来更容易理解,我们需要使用 C 语言的 typedef 关键字来为复杂类型起别名。

实验:

如下是 Linux/UNIX 操作系统信号设置函数的声明,分析该函数是怎样一个函数,该函数如何调用,实参是什么类型?返回值是什么类型?

#include <signal.h>

void (*signal(int sig, void (*func)(int)))(int);