指针
-
指针是什么?
-
指针与指针类型
-
野指针
-
指针运算
-
指针与数组
-
二级指针
-
指针数组
1.指针是什么?
指针理解的两个要点
-
指针式内存中一个最小单元的编号,也就是地址
-
平时口语中说的指针,通常是指指针变量,只用来存放内存地址的变量
总结:指针就是地址,是每一个内存的独立的编号,把这个编号称为指针,也就是地址,口语中说的指针通常是指指针变量
当创建一个变量时,比如一个整型a,a占四个字节,那么a的地址通常是a所占空间的第一个字节的地址
取地址时,可以定义一个指针变量将a的地址存起来int* pa=&a; P是一个指针变量,通常来说pa是一个指针
内存单位的地址是由硬件生成的,这些地址是不需要单独储存起来的
当我们创建变量后,一个char需要一个字节,在计算机中最小的单位就是bit,一个字节是八个比特位,我们发现,如果使用bit的地址的话,一个char就需要八个地址,会造成资源浪费,所以我们使用了byte这样一个单位来表示8个bit,正好是一个字符的大小,
地址的产生
对于32为的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电压和低电压,就是1或者0,那么32根地址线产生的地址就会是
00000000000000000000000000000000
00000000000000000000000000000001
………………
11111111111111111111111111111111
就会有2^32个地址
每一个地址标识一个字节,那我们就可以给2^32byte==4GB的空间进行编址。
按照上面的描述,一个地址就是4个字节的空间,所以这个机器的指针变量的大小就是4个字节。如果一个机器是64位地址线的话,指针变量的大小就是8个字节,在编译器中,X86的环境就是32位,X64的环境就是64位
指针类型的意义
既然指针都是用来寻找内存中的数据的,那为什么指针还要分为int*,double*……等等
int a=0x11223344; //a是16进制数字,刚好占四个字节32位
int* pa =&a;
*pa =0;//改变a的数值
所以上述的改动改变了4个字节
那么当我写这样一个代码
int a=0x11223344;
char* pa=&a;
*pa =&a;
在编译器中这串代码会报警告,因为&a的指针变量应该是int*,而不是char*,但是char*仍然能放得下这个地址,
我们在调试的时候,pa依然是a的地址,但用的时候会有差异。
此时虽然存放下了a的地址,但这个代码在往下走的时候,在*pa=0;这时,我们发现a并没有变成零,发现只改了a其中的一个字节,是因为char的大小只有一个字节。
所以指针类型决定了在解引用的时候,引用多少个字节。
此结论可以推广到其他类型,所以指针类型是有意义的,这是指针类型的第一个意义。
int main()
{
int a= 0x11223344;
int* pa=&a;
char* pc=&a;
printf("%p\n",pa);
printf("%p\n",pc);
}
这时两者打印出来的地址是一样的
但如果
printf("%p\n",pa);
printf("%p\n",pa+1);
printf("%p\n",pc);
printf("%p\n",pc+1);
我们打印pa+1的时候,就会出现差别
![](https://img-blog.csdnimg.cn/direct/2f6b9e3776b54a3e8ad41c885e294c6a.png)
pa到pa+1,加了四个字节
pc到pc+1,加了一个字节
所以,
指针类型决定了指针+1或-1操作时候跳过几个字节,这是非常合理的,对内存访问会更加方便
但是如果两个指针类型所指的变量大小一样,比如int与float的大小是一样的,但是不可以通用,原因:
int 0;
int* pi=&a;
float* pf=&a;
当我们进行修改的时候,我们改变a的值
*pi=100;
调试的时候,我们在内存中可以看到放入了,64(16进制),等于100
但是用*pf=100.0;的时候,我们发现这个内存中的值并不是100的十六进制64。这是由于不同类型的数据在内存中的存储方式并不一样。