在C语言中,指针无疑是占有非常重要的地位,也是有一些难度的知识点。在这篇文章中,将叙述指针最基础的部分——什么是指针?有什么用?怎么使用?
=========================================================================
内存
想弄清指针就要先弄清内存。
内存是电脑上特别重要的存储器,计算机所有程序的运行都是在内存中进行的。所以为了能够高效的使用内存,该如何管理内存呢?
内存就是一个空间,其实对于内存的使用,与现实中对于空间的使用有很多相似的地方。
在现实生活中,世界非常大,为了方便找到某些位置,我们给每个地方都编上了有效的地址,比如:
“北京市丰台区北京联合大学6号楼103宿舍”
当有了这个地址,我们就可以精确的找到这个房间。
其实对于内存来说也是一样的,内存就是一个很大的空间,他借鉴了我们现实生活中的一些情况
假设这个方框就是内存里的空间,在这里面又划分出了许多小空间。
1 2 3 4 5 6 7 .........
像这样,最后在给每个小空间编上号,这就是内存的管理方式。
---------------------------------------------------------------------------------------------------------------------------------
当然,内存的编号不会是这么简单的123456......那么内存是怎样编号的呢?
在谈论计算机时都会讲到是32位或是64位,而这32位,64位指的就是地址线的数量。
地址线是物理线,他可以通电,当通正电时就是 1 ,通负电时就是 0 。
当32根地址线全部通上电时,有正有负,产生的是1和0的数字序列,这个过程就将电信号转换成了数字信息,得到一串二进制序列。
以32根地址线为例,每根线输出一个0或1,32根总共可以输出一个32位的二进制数。
00000000 00000000 00000000 00000000
......
01111111 11111111 11111111 11111111
10000000 00000000 00000000 00000000
......
11111111 11111111 11111111 11111111
这32位一共可以产生2^32种排列,而这些都可以作为内存的编号,也就是说一个32位的计算机的内存有2^32个内存单元。当有了这些编号之后,我们就把他称为内存单元的地址。
---------------------------------------------------------------------------------------------------------------------------------
既然有这么多个内存单元,那么一个内存单元管理多大空间合适呢?
计算机中的单位
8bit = 1byte
1024byte = 1kb
1024kb = 1mb
1024mb = 1gb
1024gb = 1tb
1024tb = 1pb
依据这些,假设一个存单元是1bit。
那么内存中总共可以存储 2^32bit ,根据上面的换算不难得出总共可以存储0.5gb大小。这个大小还是太小了,毕竟在最早期32位电脑时2gb内存的电脑就已经非常常见了。所以一个内存单元存储一个比特位是不太合适的。
从另一个角度分析也不难发现,C语言中最小单位是 char 类型,一个 char 类型大小是1byte,也就是8bit。如果一个 bit 给一个地址,那么一个 char 类型就要给8个地址,这未免有些太细了,就好比留快递地址是:
“北京市北京联合大学6号楼103宿舍第5平米”
所以不太合适,因为 char 类型是一个字节,所以一个内存单元分配一个字节这个大小是合适的,既不会分的太细,又不会分的过于粗糙。
=========================================================================
取地址
int a = 10;
当我们创建一个变量a时,要为他分配地址,a是四个字节,需要分配4个地址,分配到的地址是连续的,如:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
00000000 00000000 00000000 00000011
这时对于查找a这个变量,因为他是连续的,所以并不需要知道每个字节的地址,取地址时只需要取出第一个字节的地址,就可以找到a这个变量的所在位置了。也就是说当 &a 时得到的结果就是 00000000 00000000 00000000 00000000 了。在实际编译过程中得到的结果不是这个,这里只是作为示例方便理解。
=========================================================================
指针
指针变量
#include<stdio.h>
int main()
{
int a = 10;
printf("%p\n",&a); //%p是专门用来打印地址的
int * pa = &a; //pa是用来存放地址的,c语言中pa叫做指针变量
// * 说明pa是指针变量
// int 说明pa执行的对象是int类型的
return 0;
}
pa 就是指针变量,而创建指针变量的方式就是
int * pa = &a
举一反三不难发现,字符类型的取地址方式是与之类似的
char ch = 'w';
char * pc = &ch;
需要注意的是这里的 * 是给前面变量类型的,而不是 pa 的,需要注意区分,与后面提到的解引用做区分。
---------------------------------------------------------------------------------------------------------------------------------
解引用操作
我们前面创建指针变量肯定不只是为了找到他,而是为了通过指针找到他去操作他里面的对象。这是指针最核心的一点。
#include<stdio.h>
int main()
{
int a = 10;
int* pa = &a;
*pa = 20; // *解引用操作符
printf("%d\n",a);
return 0;
}
*pa 就是通过 pa 里的地址找到 a ,*pa = 20 就相当于改变了a。这是一个间接的改变,通过地址找到 a ,然后再通过 pa 去改变了a。
---------------------------------------------------------------------------------------------------------------------------------
到此为止不难发现,指针就是地址。
---------------------------------------------------------------------------------------------------------------------------------
指针变量的大小
#include<stdio.h>
int main()
{
printf("%d\n",sizeof(char*)); //4
printf("%d\n",sizeof(short*)); //4
printf("%d\n",sizeof(int*)); //4
printf("%d\n",sizeof(long*)); //4
printf("%d\n",sizeof(long long*)); //4
printf("%d\n",sizeof(float*)); //4
printf("%d\n",sizeof(double*)); //4
return 0;
}
运行代码得出结果,无论什么类型的指针变量长度都为4字节。为什么呢?
指针是用来存放地址的,指针需要多大空间,取决于地址的存储需要多大空间。
32位机器输出就是32比特位,也就是4字节,64位机器输出就是64比特位,也就是8字节。
也就是说指针变量的大小是4还是8取决于是多少位的机器,只要足够存放地址的大小就足够了,所以指针变量长度都时相同的。