C++基础_指针
内存四区
a) 代码区。代码
b) 全局区。全局的常量字符串常量“ABC” 变量
c) 栈区。系统自动开辟,系统自动释放,并不是很大
d) 堆区。动态开辟的内存,手动开辟,手动释放。大
地址
把内存以单个字节为单位,分开,每一个编号,这个编号就是地址。
a) 编号是连续的
b) 唯一的
c) 取地址运算符:&单目运算符 优先级() [],结合性右往左
int a;
&a;
首地址
一段内存空间的第一个存储单元的地址
指针变量
1.用来存放地址的变量,2.内存大小4个字节
地址是编号,一种数据
整数 int a;
字符 char c;
小数 float b;
地址 指针变量
a) 指针变量的定义
int main(){
int a;
float b;
char c;
int *p; // 定义一个指针变量p,存的是地址。int指名指针指向的数据类型,*指名p这个变量是一个指针变量
}
b) 指针变量的赋值
int a = 5;
int *p;
p = &a; //p指向a
c) 指针的引用
int a = 5;
int *p;
p = &a;
printf("a=%d", a);
printf("a=%d", *p);
访问a这个变量:
- 使用变量名,
- 指针访问:指针变量。取值运算符,返回某一个地址中的值,单目运算符 右到左
注意了:再定义指针变量的时候int *p; 只是表明p是一个指针变量。而非定义的时候p则是取值p指向的内存值。
补充
野指针:不能明确指向的指针变量。危险。
int *p; // p里面保存的地址不确定,p的指向不明确的,重要数据有可能被操作到
解决方法:int *p = NULL;
空指针:int* float* char* double*
void* 转换成其它的数据类型
指针变量的运算:+ - ++ -- 只是作指针的偏移,去访问地址旁边的一些内存
指针变量的加减,是以指针所指向的类型空间为单位进行偏移
int main(){
char *p; // 一个char占1个字节,则p + 1表示p指向的地址偏移一个字节
int *p1; // 一个int占4个字节,则p1 + 1表示p1指向的地址偏移4个字节
double *p2; // 一个double占8个字节,则p2 + 1表示p2指向的地址偏移8个字节
}
一维数组与指针
- 定义一个一维数组,数组名是这个数组的“首地址”
int main()
{
int a[5];
printf("a = %d\n", a);
printf("&a = %d\n", &a);
printf("a+1 = %d\n", a + 1);
printf("&a+1 = %d\n", &a + 1);
return 0;
}
结果:
a = 13630344
&a = 13630344
a+1 = 13630348
&a+1 = 13630364
解析:
a 指向a[0], a[0]是int元素, a的类型就是 int*
a 指向a[0] int元素, int* 4字节
&a 这个地址指向整个数组, &a的类型就是 int(*)[5];(数组的指针)
- 访问数组的元素:
a) 下标法:a[0] a[1]
b) 指针法:
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* p = a; // p指向a[0]
/*
p指向a[0]的地址
p+1指向a[1]的地址
...
p+4指向a[4]的地址
则取地址的值,使用取值运算符* *p、*(p+1)...*(p+4)
*/
for (int i = 0; i < 5;++i) {
printf("%d ", *(p + i)); // 或者这样:printf("%d ", *p++);
}
// 结果为:1 2 3 4 5
return 0;
}
一些细节解析:
- 和 ++ 是单目运算符,优先级相同,从右往左结合
- 是双目运算符,优先级<和++
所以(p+i)要加括号,而p++不需要(p++,先p++结合,然后再与*结合)
当然也可以这么写:
for (int i = 0; i < 5;++i) {
printf("%d ", *(a+i)); // 这里不能用*a++,因为a是数组名,也是第一个元素的首地址,但它永远都是数组名,这个主要意义不能忽略,所以就不能去a++
}
再次强调:
1. 数组名是这个数组的首地址
2. 首地址就是一段内存中第一个存储单元的地址
二/多维数组与指针
需要知道:三维数组的存储单元是一个二维数组,二维数组的存储单元是一个一维数组,一维数组的存储单元是一个元素
int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- 数组名a是这个二维数组的首地址,这个数组在内存中的第一个存储单元是a[0],即这个一维数组
a的类型是:(数组的指针)int(*)[4]; 所以a+1 偏移16字节 - a[0]是一维数组的数组名,a[0]指向a[0][0];
a[0]的类型是:(int类型指针)int*; 所有a[0]+1 偏移4个字节
#include <iostream>
using namespace std;
int main()
{
int a[2][3] = { {1, 2, 3}, {4, 5, 6} };
printf("a[1][2] = %d\n", a[1][2]); // 结果为:6
printf("a[1][2] = *(a[1] + 2) = %d\n", *(a[1] + 2)); // 结果为:6
printf("a[1][2] = *(a[1] + 2) = *(*(a+1) + 2) = %d\n", *(*(a + 1) + 2)); // 结果为:6
cout << *(a + 1) << endl; // 随机内存地址 00CFFEB0
cout << a << endl; // 随机内存地址 00CFFEA4
cout << *a << endl; // 随机内存地址 00CFFEA4
return 0;
}
int a[3][4]
a 类型是:int()[4],a指向首地址,也指向a[0]
&a 类型是:int()[3][4], &a指向整个数组
a[0] 类型是:int*,a[0]指向一维数组的元素
a[0][0] 类型是:int,a[0][0]是一个元素,他的类型就是int类型
指针数组: int*[]
数组指针: int(*)[]
请相信自己
当我们迷茫,懒惰,退缩的时候 我们会格外的相信命运 相信一切都是命中注定
而当我们努力拼搏,积极向上时 我们会格外的相信自己
所以命运是什么呢? 它是如果你习惯它 那它就会一直左右你
如果你想挣脱它 那它就成为你的阻碍 可如果你打破了它 那它就是你人生的垫脚石!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!