转载

那些总是难以记住的 C 语言中的类型声明

指针

指针是一个变量,它的值是内存地址。

指针的类型,就是从指针所指的值的类型。

指针所指的值,就是存储于内存中的数据片段,这个数据片段的长度由指针的类型来决定。这个数据片段的起始位置就是指针的值。

常量指针与指针常量

const int *p ,请和我一起念:

  • p 是一个变量;

  • *p 是一个指针(变量);

  • int *p 是一个指针,指向一个整型值;

  • const int *p 是一个指针,指向一个整型值,这个整型值是一个常量。

这种指针类型的变量叫做 常量指针 ,它指向一个常量。这就意味着,这个指针所指的值(内存中某种类型的数据)不可以被修改,但是这个指针的值(内存地址)是可变的。

int const *p ,请和我一起念:

  • p 是一个变量;

  • *p 是一个指针(变量);

  • const *p 是一个不变的指针(常量);

  • int const *p 是一个不变的指针,它指向一个整型值。

这样的指针就叫做 指针常量 ,它的值(内存地址)不可以被改变,但是它所指向的值(内存中某种类型的数据)可变的。

发现规律了么?规律就是 从右向左念

数组指针与指针数组

int *a[4] ,请和我一起念:

  • [4] 是包含 4 个元素的数组;

  • a[4] 是包含 4 个元素的数组,这个数组的名字叫 a

  • *a[4] 是包含 4 个指针类型的元素的数组,这个数组的名字叫 a

  • int *a[4] ,是包含 4 个指向整型值的指针类型的元素的数组,这个数组的名字叫 a

这样的数组,叫做 指针数组 ,因为它的元素是指针类型。

发现规律了么?规律就是 从右向左念

int (*a)[4] ,请和我一起念:

  • () 是一对括号,它从屏幕里伸了出来,以至于我们首先看到了它;

  • (*a) 括号里有一个指针;

  • (*a)[4] 括号里有一个指针,这个指针指向包含 4 个元素的数组;

  • int (*a)[4] 括号里有一个指针,这个指针指向一个包含 4 个整型值的数组。

这样的指针,叫做 数组指针 ,因为它指向的是一个数组类型。

发现规律了么?规律就是 从右向左念,但是先念括号里的,然后再从右向左念。将括号想象成是一根从屏幕里伸出来的柱子,我们看到了它在屏幕上的投影

返回指针的函数与函数指针

int *a(char *s) ,请和我一起念:

  • () 是一根柱子,从屏幕里伸了出来;

  • (char *s) 是一根柱子,它的顶面有 char *s ,C 编译器将这样的柱子称为 函数

  • a(char *s) 是一个函数,这个函数的名字 a

  • *a(char *s) 函数 a 返回指针;

  • int *a(char *s) 函数 a 返回整型指针。

这种函数,叫做 返回指针类型的函数

int (*a)(char *s) ,请和我一起念:

  • (*a) 是一个指针,与数组指针里的那个 (*a) 没什么本质上的不同;

  • (*a)(char *s) 是一个指针,它指向一个函数;

    * int (*a)(void) 是一个指针,它指向一个函数,这个函数返回 int

这种指针,叫做 指向函数的指针 ,简称 函数指针

发现规律了么?规律就是先看有没有柱子。如果有多根柱子,那么就从左向右看这些柱子,将每根柱子所代表的东西念出来,然后再从右向左念。

自定义类型

typedef int MyInt ,请和我一起念:

  • MyInt 是我们自定义的一个类型,这个类型的名字叫 MyInt

  • typedef int MyInt ,是我们自定义的一个类型,这个类型的名字叫 MyInt ,它对应于 C 语言内建的 int 类型。

编译器在遇到 MyInt 类型时,就会将它替换为 int

发现规律了么?规律就是从右向左念,右边第一个出现的『单词』就是我们要定义的类型名,然后这个单词与 typedef 之间的部分,就是这个类型名所对应的类型。

typedef int (*MyFunc) (void) ,请和我一起念:

  • MyFunc 是我们自定义的一个类型,这个类型的名字叫 MyFunc

  • typedef int (*MyFunc) (void) 是我们自定义的一个类型,这个类型的名字叫 MyFunc ,它对应于一个指针类型 int (*) (void) ,这种类型的指针指向一种函数类型 int (void) ,这个函数类型是接受 void ,返回 int

发现规律了么?规律就是先看柱子,如果有多根柱子,那么最左边的柱子所代表的东西就是我们要定义的类型名,然后这个类型名与 typedef 之间的部分(从柱子的顶端往下看,然后再从右向左看)就是这个类型名所对应的类型。

正文到此结束
Loading...