指针和指针变量的概念
在C语言中,指针和指针变量是截然不同的两个概念,下面我们详细讲解一下这两个概念以及它们的区别:
指针:
指针本质上就是一个地址,它指向虚拟内存空间的某个位置。
通常,合法的指针应当是一个变量地址,这样就可以通过该指针访问、操作此变量。
指针变量:
指针变量是一个存储指针(即内存地址值)的变量。
指针变量本身就是一个普通的变量,它在内存中也有自己的内存地址,此变量的值是其它变量的地址。
32位平台的指针变量占4个字节内存空间,64位平台的指针变量占用8个字节内存空间。
总之,一句话解释它们的区别:
指针就是地址,而指针变量是存储这个地址的变量。
你可以将指针想象为一个书的页码,而指针变量则是你手上的书签,你用它来记住那个页码。
在日常编程实践中,我们经常说“通过一个指针来操作该变量”,这里的“指针”实际上指的是“指针变量”。因为我们实际上是通过指针变量这个中介,来间接引用或操作另一个变量的内容。
但为了方便和简洁,人们通常会省略“变量”这个词,直接说“指针”。
一般来说,只要在具体的上下文中清楚其意义,在实际操作时确实不需要那么扣概念,将"指针"和"指针变量"混为一谈问题也不大。
图解指针变量(非常重要)
指针变量是一个存储了其余变量地址的变量,比如下图就描述了一个指针变量通过存储一个int变量地址指向了该int变量:
在这个图中:
int变量
num = 100;:
它的地址是
0x004ffd6c,二进制表示就是0000 0000 0100 1111 1111 1101 0110 1100(32位)它存储的十进制整数100,由于小端存储法,在低地址上存储的是最低有效位。
指针变量
*p = &num:
它的地址是
0x0097f960它存储的就是变量num的地址值,由于小端存储法,从低地址到高地址存储的数据是
0110 1100 1111 1101 0100 1111 0000 0000
指针变量的声明
一个指针变量的声明方式非常简单,语法如下:
数据类型 *指针名;其中:
数据类型,表示此指针所指向的数据的数据类型。比如写int,就表示该指针指向一个int类型变量。
"*"不论在格式上紧跟数据类型,还是紧跟指针名,在语法上都是一样的,都是与指针名绑定的。也就是说:
指针变量声明的两种方式
int* p1; // 不推荐的方式 int *p2; // 推荐的方式这两种方式虽然在格式上不同,但语法上却都是表示一个"指向int类型变量的指针"。
为了体现格式和语法上的一致性,避免产生歧义,指针变量声明的语法,请在任何时候都将"*"紧贴指针名!!
指针名就是一个变量名,一个普通的标识符,星号不是指针名的一部分!!比如上述两个声明中,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语言这样的变量声明设计,主要有以下考虑:
C语言的设计哲学追求简洁、灵活。
C语言诞生时计算机的内存空间比较拮据,C语言的设计考虑了减小源文件大小。因此这样看似奇怪的声明语法,使得C语言可以一行声明多个类型不一致的变量。如:
int a, *p, arr[5]; // 三个变量,类型都不一致。分别是整型a,int指针类型p以及int数组类型arr然而,在现代编程实践中,源文件大小已不再是主要关注点,简洁也不再是程序员的主要目标。我们更重视代码的可读性和维护性,尤其在团队开发中。
为了更好的代码质量,现代编程中关于变量声明的建议如下:
尽量每行只声明一个变量,除非多个变量类型一致,作用相似。
建议将 紧跟变量名,如 "int *ptr;",以明确此变量为指针类型变量。
为变量提供有意义的注释,特别是当变量的名字无法完全描述其用途时。
使用描述性和有意义的变量名。
总之,虽然C语言的标准语法,为我们提供了很大的灵活性,但在现代编程实践中,清晰性和可读性是更关键的。
