1.什么是指针和指针变量
指针就是内存地址,指针变量就是用来存放内存地址的变量。在相同环境下,不同类型的指针变量所占用的存储单元是相同的。
指针在C语言中是最重要的特性之一,想要了解指针,要先知道什么是地址。
1.1地址
计算机将内存分割为字节(byte),每个字节能存储8位(bit)的信息,而每个字节都有唯一的地址。
地址就类似于现实生活中,宿舍房间的编号:201,314。这样能提高效率,更快速更准确的找到房间。
需要注意的是计算机中内存的编址,并非像宿舍门上的门牌号一样把每个地址单独记录下来,而是通过硬件设计完成的。
2.指针和指针变量
指针就是地址,是内存中最小单元的编号
可以理解成:
指针==地址==内存单元的编号
指针变量就是存储地址的变量
举例:
通过下面的代码可以打印出变量的地址:
#include <stdio.h>
int main()
{
int n = 10;
printf("%p", &n);
return 0;
}
%p 打印地址操作符
& 取地址操作符
运行结果:
当我们需要把地址存入一个变量中去时,就需要用到指针变量
举例:
#include <stdio.h>
int main()
{
int n = 10;
int* p = &n;
*p = 11;//通过指针改变n的值
printf("&n= %p\n", &n);
printf("p = %p\n", p);
printf("n = %d\n", n);
printf("*p= %d\n", *p);
return 0;
}
* 解引用操作符
运行结果:
通过程序运行结果可以看到:
指针变量p中存放的就是n的地址
通过*p可以对n的值进行更改,可以理解为当p指向n时,*p就是n的别名
总结:
p就是指针变量,它是指向int型变量n的指针变量
当指针p的值为对象n的地址时,一般说“p指向了n”
*p的值就是p指向的n的值
&n也是指向n的指针
把取地址运算符&写到int型对象n前得到的&n为int *型指针,其值为n的地址
需要注意p的类型是 int *
指针变量也可以指向另一个指针,即指向指针的指针。
3.指针的大小,和类型
举例:
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(float*));
printf("%d\n", sizeof(double*));
printf("%d\n", sizeof(double*));
printf("%d\n", sizeof(void*));
return 0;
}
运行结果
截图为x64环境,可以看出,在相同环境下,指针变量的大小与类型无关,大小都是相同的
2.1指针的算数运算
举例:
#include <stdio.h>
int main()
{
int n = 3;
char* p1 = (char*) & n;
int* p2 = &n;
printf("&n = %p\n\n", &n);
printf("p1-1 = %p\n", p1-1);
printf("p1 = %p\n", p1);
printf("p1+1 = %p\n\n", p1+1);
printf("p2-1 = %p\n", p2-1);
printf("p2 = %p\n", p2);
printf("p2+1 = %p\n", p2+1);
return 0;
}
运行结果
上面代码中char*类型的指针变量+-1时只跳过了一个字节,而int*类型的指针+-1时跳过了四个字节,这说明了,指针变量的类型移动一步的距离(字节数)。
2.2用const修饰指针和保护参数
使用const修饰的变量不会被改变,被修饰的这个变量叫常变量,本质上还是变量,只是不能被修改
看下面的例子,观察使用const修饰变量的结果
结论:当没用const时,n的值既可以直接改变,也可以通过指针变量改变
结论:当使用const修饰n时,想要直接改变n的值编译器会报错,但可以通过指针变量*p修改。
再看下面的代码
结论:当使用const修饰指针变量时,试图改变*p时编译器会报错,而n本身却并不受影响
总结:const修饰的常变量不能被直接修改,但可以第三方修改,当我们需要保证常变量的可靠时,可以把第三方也用const修饰。
const拓展:
前面的代码
const int * p = &n;
也可以写成
int const * p = &n;
这两者并没有什么区别,但是当把const放在*的右边时就会有不同的效果
结论:const在修饰指针变量时,const在*左边和右边有着不同的结果
1.const放在*左边修饰的是指针指向的内容,指针指向的内容不能通过指针修改,但是指针变量本身的内容可以改变。
2.const放在*右边修饰的是指针变量本身,指针变量不能被修改,但是指针指向的内容可以通过指针修改。