char * const *(*next)();

next 是一个函数指针,它指向一个函数

该函数没有参数,返回类型为一个指针类型

该指针指向一个类型为 char 的常量指针

  • 函数的返回值不能是一个函数
  • 函数的返回值不能是一个数组
  • 函数的返回值允许是一个函数指针
  • 函数的返回值匀速是一个指向数组的指针
  • 数组里面允许有函数指针
  • 数组里面允许有其他数组
关于结构(struct)
结构就是一种把一些数据项组合在一起的数据结构。其他编程语言把它称为记录(record)。
结构的内容可以使任何其他数据声明:单个数据项、数组、其他结构、指针等。
结构的通常形式:
struct 结构标签(可选)
{
类型 标识符;
类型 标识符;
...
}变量定义(可选);
结构中允许存在位段、无名字段以及字对齐所需的填充字段。这些都是通过在字段的声明后面加一个冒号以及一个表示字段位长的整数来实现的。
struct pid_tag
{
unsigned int inactive : 1; // 1 bit
unsigned int : 1; // 填充 1 bit
unsigned int refcount : 6; // 6 bit
unsigned int : 0; // 填充到下一字边界 (32位机器填充24位)
short pid_id; // 2字节(字节对齐后占用 4 字节空间)
struct pid_tag *link; // 4字节
};

//sizeof(struct pid_tag);结果为 12 字节
参数在传递时首先尽可能地存放到寄存器中(追求速度)。
两个跟结构有关的参数传递问题
  1. 注意, int 型变量 i 跟只包含一个 int 型成员的结构变量 s 在参数传递时的方式可能完全不同。一个 int 型参数一般会传递到寄存器中,而结构参数则很可能被传递到堆栈中。
  2. 在结构中放置数组,可以把数组当作第一等级的类型,用赋值语句拷贝整个数组,以传值调用的方式把它传递到函数,或者把它作为函数的返回类型。
关于联合(union)
联合在其他编程语言中被称作变体记录(variant record)。
在结构中,每个成员一次存储,而在联合中,所有的成员都从偏移地址零开始存储。这样每个成员的位置都重叠在一起:在某一时刻,只有一个成员真正存在于该地址。
在联合中,所有成员共享一块内存空间,该内存空间大小为所有成员类型中占用内存空间的最大值。
union 标签(可选)
{
类型 标识符;
类型 标识符;
...
}变量定义(可选);
#include <stdio.h>

int main()
{
union Test
{
int a;
char b;
double c;
}temp;
printf("%d\n",sizeof(temp));
return0;
}
8
Press any key to continue
关于枚举(enum)
枚举通过一种简单的途径,把一串名字与一串整型值联系在一起。
enum 标签(可选)
{
标识符[=整型值],
标识符[=整型值],
...
标识符[=整型值]
}变量定义(可选);
缺省情况下,整型值从零开始。如果对列表中某个标识符进行了初始化赋值,那么紧接其后的那个标识符的值就比所赋的值大 1 ,然后依次类推。
#include <stdio.h>
typedef int (*Array_pointer)[10];

int main()
{
enum weekday
{
MONDAY = 1, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,SATURDAY,SUNDAY
};
printf("MONDAY\t\t%02d\n",MONDAY);
printf("TUESDAY\t\t%02d\n",TUESDAY);
printf("WEDNESDAY\t%02d\n",WEDNESDAY);
printf("THURSDAY\t%02d\n",THURSDAY);
printf("FRIDAY\t\t%02d\n",FRIDAY);
printf("SATURDAY\t%02d\n",SATURDAY);
printf("SUNDAY\t\t%02d\n",SUNDAY);
return 0;
}
枚举类型在使用中有以下规定:
  1. 枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。
  2. 枚举元素本身由系统定义了一个表示序号的数值,从0 开始顺序定义为0,1,2…。
  3. 只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。如一定要把数值赋予枚举变量,则必须用强制类型转换。
枚举具有一个优点:
#define 定义的名字一般在编译时丢弃,而枚举名字则通常一直在调试器中可见,可以在调试代码时使用它们。

C 语言声明的优先级规则

A 声明从它的名字开始读取,然后按照优先级顺序读取。

B 优先级从高到低依次是:

B.1 声明中被括号括起来的那部分。

B.2 后缀标识符:

括号()表示这是一个函数

方括号[]表示这是一个数组

B.3 前缀操作符:星号 * 表示“指向...的指针”

C 如果 const 和(或)volatile 关键字的后面紧跟类型说明符,那么它作用于类型说明符。在其他情况下,const 和 volatile 关键字作用于它左边紧邻的指针星号。

typedef
typedef 说明符被称为"存储类型说明符",使用 typedef 说明符可以使语法更加方便
#include <stdio.h>
typedef int (*Array_pointer)[10];

int main()
{
int i[10] = {0,1,2,3,4,5,6,7,8,9};
Array_pointer p = &i;
for( ; ; )
{
static int temp = 0;
if(temp > 9)
break;
printf("%d ",(*p)[temp]);
temp ++;
}
printf("\n");
return 0;
}
0 1 2 3 4 5 6 7 8 9
Press any key to continue
 
typedef 为数据类型创建别名,而不是创建新的数据类型,可以对任何类型进行 typedef 声明。
typedef 关键字并不创建一个变量,而是选成“这个名字是指定类型的同义词”。
typedef 具备其他声明一样混乱的语法,同样可以把几个声明器塞到一个声明中去。(缺点)

typedef 和宏定义的区别

  1. 可以用其他类型说明符对宏类型名进行扩展,但对 typedef 所定义的类型却不能这样做。
  2. 在连续几个变量声明中,用 typedef 定义的类型能够保证声明中所有变量均为同一种类型,而用 #define 定义的类型则无法保证。

typedef 的用途

不应为了方便起见对结构使用 typedef

typedef 应该用在:

  • 数组、结构、指针以及函数的组合类型。
  • 可抑制类型。
  • typedef 也可以为后面强制转换类型提供一个简单的名字。