1.内存和地址
内存:
计算机中核心组成模块: CPU内存
CPU是执行指令,执行程序的核心控制单元
内存是存储当前执行程序的指令,二进制内容
内存分区:
内存地址:
计算机中的最小存储单元 : 字节(byte)
计算机存储的每一个字节,这些字节都有唯一的编号,这个编号就是【内存地址】
0x0 ==> NULL
0x0是内存中编号为 0 的内存,被系统保护【不可访问,不可更改】否则程序被系统直接结束
NULL 常用于变量初始化操作避免【野指针】
2.指针格式
数据类型 * 指针变量 = 初始化数据;
数据类型:
可以认为约束指针存储的变量对应的内存空间首地址,当前是什么类型的指针
* :
指针特色,指针变量标记
指针变量:
存储内存空间的首地址
初始化数据:
数据必须是一个地址,通过地址运算符或其他方式得到地址数据,赋值给指针变量
如果尚未明确指向的空间是哪一个,通常情况下指针变量初始化为 NULL (0x0)
指针操作相关运算符
& 取地址运算符,可以获取对应变量在内存空间中的【首地址】
* 取值运算符,通过访问变量存储的地址,CPU访问对应的地址,取值变量数据
案例代码
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
//数据类型 * 指针变量 = 初始化数据
//自定义初始化指针变量 p 初始化为 NULL,存在栈区
int * p = NULL;
//定义一个int类型变量,变量名为 num
//所在内存为栈区
int num = 10;
// & 取地址操作,获取当前变量首地址
cout << &num << endl;
//指针变量 p 存储 num 首地址
p = #
//查看取地址情况
cout << p << endl;
// * 取值运算符,通过索取首地址访问对应内存取值存储数据
cout << *num << endl;
cout << *p << endl;
return 0;
}
结果如下
指针变量占用的空间字节数
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
/*
各种类型指针变量定义
*/
short *p1 = NULL;
int *p2 = NULL;
long *p3 = NULL;
char *p4= NULL;
float *p5= NULL;
double *p6= NULL;
bool *p7= NULL;
cout << "sizeof(p1)" << sizeof(p1) << endl;//8字节
cout << "sizeof(p2)" << sizeof(p2) << endl;//8字节
cout << "sizeof(p3)" << sizeof(p3) << endl;//8字节
cout << "sizeof(p4)" << sizeof(p4) << endl;//8字节
cout << "sizeof(p5)" << sizeof(p5) << endl;//8字节
cout << "sizeof(p6)" << sizeof(p6) << endl;//8字节
cout << "sizeof(p7)" << sizeof(p7) << endl;//8字节
return 0;
}
结果如下
址传递 and 值传递
值传递代码如下
#include <iostream>
using namespace std;
void swap1(int num1 , int num2);
int main(int argc, char const *argv[])
{
int num1 = 10;
int num2 = 20;
cout << "函数调用之前" << endl;
cout << "num1 : " << num1 << endl; // 10
cout << "num2 : " << num2 << endl; // 20
swap1(num1, num2);
cout << "\n函数调用之后" << endl;
cout << "num1 : " << num1 << endl; // 10
cout << "num2 : " << num2 << endl; // 20
return 0;
}
void swap1(int num1 , int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
代码运行之后函数内部虽然执行数据交换操作但是 main 函数里面的值未变,只是经历了这个操作并没有返回给 main 函数
址传递代码如下
#include <iostream>
using namespace std;
/*
数据交换函数,所需参数是两个指针,指针对应的数据类型为 int 类型
@param p1 指针类型,指向空间数据类型为 int 类型
@param p2 指针类型,指向空间数据类型为 int 类型
*/
void swap2(int *p1, int *p2);
int main(int argc, char const *argv[])
{
int num1 = 10;
int num2 = 20;
cout << "函数调用之前" << endl;
cout << "num1 : " << num1 << endl; // 10
cout << "num2 : " << num2 << endl; // 20
swap2(&num1, &num2);
cout << "\n函数调用之后" << endl;
cout << "num1 : " << num1 << endl; // 20
cout << "num2 : " << num2 << endl; // 10
return 0;
}
void swap2(int *p1, int *p2)
{
//*p1 CPU根据p1指针变量存储的地址,访问对应的数据空间,取消 int 类型
int temp = *p1;
//CPU 通过 p2 指针存储的地址,取值数据,赋值给p1指向内存
*p1 = *p2;
//temp 赋值给 p2 指针指向的空间
*p2 = temp;
}
通过函数调用里面的数值交换之后,利用取地址运算符得到交换之后的地址从而完成数据交换
二级指针
是指用一个指针指向另外一个指针指向的地址
图例如下:
代码如下
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num = 100;
// 一级指针,存储 int 类型变量的空间首地址
int * p = #
// 二级指针,存储 int 类型指针变量空间首地址
int ** q = &p;
// num 空间首地址
printf("&num = %p\n", &num);
printf("p = %p\n", p);
// 相当于根据二级指针存储的 一级指针变量首地址,取值一级指针存储的地址
printf("*q = %p\n", *q);
printf("-------------------------------\n");
// num 存储的数据情况
printf("num = %d\n", num);
printf("*p = %d\n", *p);
printf("**q = %d\n", **q);
return 0;
}
指针数组
首先是一个数组
数组中的每一个元素都是一个指针
代码案例如下:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num1 = 100;
int num2 = 200;
int num3 = 300;
// 定义了一个 int 类型指针数组,容量为 3
// 每一个元素都是一个 int 类型的指针。
int * arr[3] = {NULL};
// 将变量取地址存储操作,存储到对应的数组中
arr[0] = &num1;
arr[1] = &num2;
arr[2] = &num3;
//【重点】数组中每一个元素,存储的内容都是地址
printf("arr[0] = %p\n", arr[0]);
printf("arr[1] = %p\n", arr[1]);
printf("arr[2] = %p\n", arr[2]);
printf("\n");
// 【重点】通过数组中的指针取值操作,获取对应变量的数据
printf("*arr[0] = %d\n", *arr[0]);
printf("*arr[1] = %d\n", *arr[1]);
printf("*arr[2] = %d\n", *arr[2]);
printf("\n");
// 【重点】利用数组名通过累加的方式获取数组元素存储地址对应的变量数据内容
printf("**(arr + 0) = %d\n", **(arr + 0));
printf("**(arr + 1) = %d\n", **(arr + 1));
printf("**(arr + 2) = %d\n", **(arr + 2));
printf("\n");
printf("arr[0] = %p\n", arr[0]);
printf("*arr + 5 = %p\n", *arr + 5);
return 0;
}
今天分享到此结束啦!! 我们下次再见!!!