目录
一、计算机程序在存储数据时的三要素
- 信息存储在何处
- 存储的值是多少
- 存储的信息是什么类型
二、内存的四个区
- 代码区,存储代码片
- 全局区,存储全局的常量,比如:字符串常量“abcdefg”、static、const
- 栈区,系统自动开辟的,不大,比如:for (int i = 1; i <= n; i++)此处的局部变量 i 所占用的内存空间是系统自动开辟的
- 堆区,动态开辟,手动释放,很大,比如:new,delete
三、指针变量的3个基本定义
- 地址:把内存以单个字节为单位分割,每个字节编号,这个编号就是地址。a) 编号连续 b) 唯一 c) 取地址符‘&’:单目运算符,优先级只比'()'、'[]'、'.'低;结合顺序:右向左。
- 首地址:一段内存空间中第一个存储单元的地址。(此处存储单元:低维度数组)。
- 指针变量:用来存放地址的变量,占用4Bytes内存。
四、指针的声明与初始化
/*
指针声明
*/
int* ptr; // ptr的类型是指向int的指针,或者ptr的类型是int*
double* dptr; // dptr的类型是指向double的指针,或者dptr的类型是double*
/*
指针初始化
*/
int variable = 10;
int* ptr = &variable;
五、指针的危险
在C++中创建指针的时候,计算机将分配用来存储地址的内存,但是不会分配用来存储指针所指向的内存,因为为数据提供空间是一个独立的步骤。
- 野指针:不能明确指向的指针变量
- 空指针:void* 可以先这么定义然后转换成其它的数据类型
WARNING:一定要在对指针应用解除引用运算符' * '之前,将指针初始化为一个确定的、适当的地址。
/*
使用错误,23333不是一个已经分配了内存空间的变量,int* 类型的指针ptr只是一个存储地址的4B空间
*/
int* ptr;
*ptr = 23333;
/*
定义void* 类型指针ptr,赋值 a 的地址,然后将 void* 类型转化为 int* 类型的指针并通过
解除引用运算符‘*’进行数值输出
*/
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
void* ptr;
int a = 3;
ptr = &a;
cout<< *(int*)ptr<< endl;
return 0;
}
六、指针的四种运算
指针只有四种运算:' + '、' - '、' ++ '、' -- ',偏移。
指针变量的加减,以指针所指向的类型空间为单位进行偏移。
例如:
- char* ptr; char的大小是 1B,因为 ptr 的类型为 char*,所以 ptr+1 的偏移量是 1B
- int* ptr; int的大小是4B,因为 ptr 的类型为 int*,所以 ptr+1 的偏移量是 4B
- double* ptr; double的大小是8B,因为 ptr 的类型是 double*,所以 ptr+1 的偏移量 8B
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int a[5] = {1, 2, 3, 4, 5};
// 数组名表示首地址
cout<< "a= "<< int(a)<< endl;
cout<< "a+1= "<< int(a+1)<< endl;
// 对数组进行取地址 &,得到的并不是数组的首地址,而是整个数组,也就是 int(*)[5]
cout<< "&a = "<< int(&a)<< endl;
cout<< "&a+1 = "<< int(&a+1)<< endl;
return 0;
}
输出:
a = 2686684
a+1 = 2686688 // 首地址a[0],故而a的类型是int*,所以a+1增加4B
&a = 2686684
&a+1 = 2686704 // &a的类型是int(*)[5],所以&a+1增加4x5=20B
七、指针与多维数组
int a[1][2][3][4][5][6][7][8];
&a | 8维 | int(*)[][][][][][] |
a | 7维 | int(*)[][][][][] |
a[] | 6维 | int(*)[][][][] |
a[][] | 5维 | int(*)[][][] |
a[][][] | 4维 | int(*)[][] |
a[][][][] | 3维 | int(*)[] |
a[][][][][] | 2维 | int* |
a[][][][][][] | 1维 | int |
八、指针的引用
- 下标法 a[m][n]
- 指针法 *(a[m] + n) 或者 *(*(a + m) + n)
九、动态分配内存
C++的new运算符,将找到一块长度正确的内存块,并返回该内存块的地址。
int* p = new int; // 分配一个int大小的空间
char* p = new char; // 分配一个char大小的空间
int* p = new int[32]; // 分配一个长度为32的int数组的空间
char* p = new int[32][32]; // 分配一个大小为32x32的char二维数组的空间
delete p; // 释放空间
delete[] p; // 释放数组空间
new和delete要搭配使用。使用new运算符在自由存储空间(或者堆)上创建变量之后,没有调用delete,即使包含指针的内存由于作用域规则和生命周期的原因被释放,但是在自由存储空间上动态分配的变量或者结构依然存在。
十、指针和函数(数组和函数)
/*
get_variable函数和show_arr函数中的第一个参数 int arr[]和int* arr都表示arr是一个
int类型的指针
*/
#include<iostream>
#include<cstdio>
using namespace std;
void get_variable(int arr[], int length)
{
for (int i = 0; i < length; i++)
{
arr[i] = i+1;
}
}
void show_arr(const int* arr, int length)
{
for (int i = 0; i < length; i++)
{
cout<< arr[i]<< " ";
}
cout<< endl;
}
int main()
{
int arr[5];
get_variable(arr, 5);
show_arr(arr, 5);
return 0;
}
十一、指针和const
- 指针指向一个const对象(常量对象):防止指针更改所指向的值
- 将指针本身声明为const(常量):防止指针指向其它的位置