C语言中的指针

_

指针和指针变量的概念

在C语言中,指针和指针变量是截然不同的两个概念,下面我们详细讲解一下这两个概念以及它们的区别:

  1. 指针:

    1. 指针本质上就是一个地址,它指向虚拟内存空间的某个位置。

    2. 通常,合法的指针应当是一个变量地址,这样就可以通过该指针访问、操作此变量。

  2. 指针变量:

    1. 指针变量是一个存储指针(即内存地址值)的变量。

    2. 指针变量本身就是一个普通的变量,它在内存中也有自己的内存地址,此变量的值是其它变量的地址。

    3. 32位平台的指针变量占4个字节内存空间,64位平台的指针变量占用8个字节内存空间。

总之,一句话解释它们的区别:

指针就是地址,而指针变量是存储这个地址的变量。

你可以将指针想象为一个书的页码,而指针变量则是你手上的书签,你用它来记住那个页码。

在日常编程实践中,我们经常说“通过一个指针来操作该变量”,这里的“指针”实际上指的是“指针变量”。因为我们实际上是通过指针变量这个中介,来间接引用或操作另一个变量的内容。

但为了方便和简洁,人们通常会省略“变量”这个词,直接说“指针”。

一般来说,只要在具体的上下文中清楚其意义,在实际操作时确实不需要那么扣概念,将"指针"和"指针变量"混为一谈问题也不大。

图解指针变量(非常重要)

指针变量是一个存储了其余变量地址的变量,比如下图就描述了一个指针变量通过存储一个int变量地址指向了该int变量:

指针变量-示意图

在这个图中:

int变量num = 100;

  1. 它的地址是0x004ffd6c,二进制表示就是0000 0000 0100 1111 1111 1101 0110 1100(32位)

  2. 它存储的十进制整数100,由于小端存储法,在低地址上存储的是最低有效位。

指针变量*p = &num

  1. 它的地址是0x0097f960

  2. 它存储的就是变量num的地址值,由于小端存储法,从低地址到高地址存储的数据是0110 1100 1111 1101 0100 1111 0000 0000

指针变量的声明

一个指针变量的声明方式非常简单,语法如下:

数据类型 *指针名;

其中:

  1. 数据类型,表示此指针所指向的数据的数据类型。比如写int,就表示该指针指向一个int类型变量。

  2. "*"不论在格式上紧跟数据类型,还是紧跟指针名,在语法上都是一样的,都是与指针名绑定的。也就是说:

    指针变量声明的两种方式
    int* p1;    // 不推荐的方式
    int *p2;    // 推荐的方式

    这两种方式虽然在格式上不同,但语法上却都是表示一个"指向int类型变量的指针"。

    为了体现格式和语法上的一致性,避免产生歧义,指针变量声明的语法,请在任何时候都将"*"紧贴指针名!!

  3. 指针名就是一个变量名,一个普通的标识符,星号不是指针名的一部分!!比如上述两个声明中,p1和p2就是指针名。

举例:

指针变量声明-代码示例
int *p;      // 声明一个指向整型的指针变量p
char *ch;    // 声明一个指向字符的指针变量ch
double *d;   // 声明一个指向双精度浮点数的指针变量d
int *p1, *p2;           // 声明两个指向整型的指针变量p1和p2
int* p3, p4;  // 避免采取这种声明方式,因为这里只有p3是指针变量,p4是普通整数变量。容易产生歧义!!

一般而言,编程语言的变量声明都会采用:"数据类型 变量名;" 的格式,而这种风潮实际上就是从C语言开始的。但我们仍然可以发现,C语言某些声明风格却显得非常特别,比如:

一些更好的声明风格展示-演示代码
int[5] arr;     // 如果这样声明数组,int[5]是数据类型,arr是数组名。但C语言不支持此风格
int* p;     // 如果这样声明指针变量,int* 表示数据类型,p是指针名。但C语言更推荐*紧跟指针名

C语言这样的变量声明设计,主要有以下考虑:

  1. C语言的设计哲学追求简洁、灵活。

  2. C语言诞生时计算机的内存空间比较拮据,C语言的设计考虑了减小源文件大小。因此这样看似奇怪的声明语法,使得C语言可以一行声明多个类型不一致的变量。如:

     int a, *p, arr[5]; // 三个变量,类型都不一致。分别是整型a,int指针类型p以及int数组类型arr

然而,在现代编程实践中,源文件大小已不再是主要关注点,简洁也不再是程序员的主要目标。我们更重视代码的可读性和维护性,尤其在团队开发中。

为了更好的代码质量,现代编程中关于变量声明的建议如下:

  1. 尽量每行只声明一个变量,除非多个变量类型一致,作用相似。

  2. 建议将 紧跟变量名,如 "int *ptr;",以明确此变量为指针类型变量。

  3. 为变量提供有意义的注释,特别是当变量的名字无法完全描述其用途时。

  4. 使用描述性和有意义的变量名。

总之,虽然C语言的标准语法,为我们提供了很大的灵活性,但在现代编程实践中,清晰性和可读性是更关键的。

评论区