《C/C++学习指南》语法篇—笔记 (八、指针)
- 提要:变量与内存
- 使用指针类型表示地址
- 关于指针
- 星号操作:按地址访问
- 指针与数组
- 指针作为函数的参数
- const指针
- 指针的安全使用
提要:变量与内存
- 内存用于存储数据,最小单元是字节(8bit),每个单元都有一个编号(地址:0x00000000~0xFFFFFFFF),地址是一个整数
- 变量大小(sizeof()返回变量大小),int型是4字节,变量的大小指它在内存中占了几个字节
- 变量地址就是该变量在内存中的位置。使用&取得该变量地址。
- 变量赋值:向内存写入数据。读变量的值,从内存中读取数据。
- 每个变量都有自己的内存地址,绝不会有两个变量内存地址相同。
- 程序每次运行,变量的地址是不一样的,无法预测。
使用指针类型表示地址
地址是整数,理论上可以用int,但是未来强调它是内存地址,使用 ==类型*==这个新类型来表示:
char* :表示一个char型变量的地址
short* :表示一个short型变量的地址
int* :表示一个int型变量的地址
float* :表示一个float型变量的地址
double* :表示一个double型变量的地址
unsigned char* :表示一个unsigned char型变量的地址
定义了一个指针类型的变量(指针),类型int*,初始值为int型变量a的地址
int a = 10;
int* ptr = &a;
关于指针
- 指针也是变量,可以改变
- 不同类型的指针,不能互相赋值 int* ptr1 与 double* ptr2
- 指针即地址,地址是整数,所以指针是一个整数类型
- 关于 * 位置
int* a
,int * a
,int *a
,建议第一种。
星号操作:按地址访问
对于一个变量 int型为例,有两种方式访问,改变它的值
(1)直接使用变量名
int = 0;
printf("a:%d",a);
a = 0x11;
(2)使用指针(按地址访问,直接修改内存)
有一个指针变量p,*p用于访问p指向的内存(读写)
int a = 0;
int* p = &a; //p指向a
printf("a:%d",*p);
*p = 0x11;
注意区分:指针定义语句种的 int*
和 按地址访问的 *p
如果只是一个单纯int型变量,不支持按地址访问的 *
操作,只有指针类型变量才可以按地址访问。虽然指针类型是int型的。
指针与数组
C/C++中,数组名就是数组的首地址,就是数组在内存中的位置。
把数组看成一块连续内存,数组名是这块内存的首地址,可以通过指针来访问它,数组与指针可以灵活转换。
int arr[4] = {1,2,3,4};
int* p = arr; //arr本身类型就是 int*
相当于
int* p = &arr[0]; //第一个元素的地址
指针加减法:
- 指针加法:后移n个元素
- 指针减法:前移n个元素
指针与数组之间的关系:
-
用p指向数组arr中的任意一个元素
p = arr+3
,p = &arr[3]
-
给数组元素赋值:
arr[3] = 10;
,*(arr+3) = 10
,int* p = arr+3; *p = 10;
-
把p可以当成数组使用:
int* p = &arr[1]; p[0] = 0xAA; //p[0]:自p开始的第0号元素,即arr[1] p[1] = 0xBB; //p[1]:arr[2]
-
数组的遍历
int arr[4]; for(int i=0;i<4;i++) {printf("%d \n",arr[i]); }int arr[4]; for(int* p = arr; p<arr+4; p++) { printf("%d \n",*p); }
-
越界访问(运行错误)
指针作为函数的参数
可以把指针作为函数的参数,把一个内存地址传给一个函数(传址)
使用指针作为参数,可以实现两种功能:
- 读取上一层函数中变量的值
*p
- 可以修改上一层函数中变量的值
*p
(普通的参数无法实现值修改)
传递数组作为参数,数组名,实质是一个指针类型,传递数组,就是传递指针。将数组信息传给一个函数,需要传递数组首地址(一片连续内存的地址)和数组长度(这块内存上存储的对象个数)。
下面两种形式完全等价:
int avg(int* p, int len)
int avg(int p[],int len)
指针作为函数的参数的作用:
- 当需要返回多个值的时候,return只能返回一个值,若一个函数需要返回多个值,必须使用指针参数(输出参数)
- 效率问题:传值与传地址,
const指针
在普通指针类型前面,加上const修饰
const int* p;
const char* p;
有无const的区别:
-
不加const: 可读可写
int a = 10; int* p = &a; *p = 11; //可写 int b = *p; //可读
-
加const修饰
int a = 10; const int* p = &a; *p = 11; //错!!!,不可写 int b = *p; //可读
所以const修饰常用限定函数的参数,有的是只读 的输入参数,有的是可以修改的输出参数。当不需要修改内存时,在指针前面加上const修饰,避免不小心的错误。
指针的安全使用
指针只允许指向两个方向:
- 指向变量,数组
- 指向0 (NULL) 空指针 此时也不能用*操作,不过可以作为程序判断。
当一个指针未赋值时,其值为随机值,刺实指向一个随机内存地址,称为野指针。
好习惯:初始化指针为空指针。