天天看点

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这个变量:

  1. 使用变量名,
  2. 指针访问:指针变量。取值运算符,返回某一个地址中的值,单目运算符 右到左

    注意了:再定义指针变量的时候int *p; 只是表明p是一个指针变量。而非定义的时候p则是取值p指向的内存值。

    C++基础_指针

补充

野指针:不能明确指向的指针变量。危险。

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个字节
}
           

一维数组与指针

  1. 定义一个一维数组,数组名是这个数组的“首地址”
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];(数组的指针)

  1. 访问数组的元素:

    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. 首地址就是一段内存中第一个存储单元的地址

二/多维数组与指针

需要知道:三维数组的存储单元是一个二维数组,二维数组的存储单元是一个一维数组,一维数组的存储单元是一个元素

C++基础_指针

int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

  1. 数组名a是这个二维数组的首地址,这个数组在内存中的第一个存储单元是a[0],即这个一维数组

    a的类型是:(数组的指针)int(*)[4]; 所以a+1 偏移16字节

  2. 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类型

C++基础_指针

指针数组: int*[]

数组指针: int(*)[]

请相信自己

当我们迷茫,懒惰,退缩的时候

我们会格外的相信命运

相信一切都是命中注定

而当我们努力拼搏,积极向上时

我们会格外的相信自己

所以命运是什么呢?

它是如果你习惯它

那它就会一直左右你

如果你想挣脱它

那它就成为你的阻碍

可如果你打破了它

那它就是你人生的垫脚石!

如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

c++

继续阅读