0
点赞
收藏
分享

微信扫一扫

Vue中 如何监听键盘事件中的按键

五殳师兄 2024-02-17 阅读 15
c语言

文章目录


嘻嘻,家人们,今天咱们剖析一下指针,好啦,废话不多讲,开干!

1:内存与地址

1.1内存

在讲解内存与地址之前,我们先来看生活中的一个案例.
如果把上面的例子对照到计算机中,又会是怎样呢?
1:bit  --- 比特位                   
2:byte --- 字节 				1byte = 8bit               
3:KB						    1KB   = 1024byte 
4:MB							1MB   = 1024KB
5:GB							1GB   = 1024MB
6:TB							1TB   = 1024GB
7:PB							1PB   = 1024TB

PS:一个比特位可以存储一个2进制的1或者0

在这里插入图片描述

1.2:如何理解编址

在这里插入图片描述

2:指针变量与地址

理解了内存与地址的关系后,再回到C语言,在C语言中创建变量其实就是向内存申请空间,我们看下面这段代码.

#include <stdio.h>
int main()
{
	int value = 15;
	return 0;
}

在这里插入图片描述

0x0113FE28  
0x0113FE29    
0x0113FE2A    
0x0113FE2B
#include <stdio.h>
int main()
{
	int value = 15;
	printf("%p\n", &value);
	return 0;
}

在这里插入图片描述

2.1:指针变量与解引用操作符

2.1.1:指针变量

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 20;
	int* pa = &a;
	return 0;
}

2.1.2:如何拆解指针类型

int a = 20;
int* pa = &a;

在这里插入图片描述

2.1.3:解引用操作符

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 100;
	int* pa = &a;
	*pa = 25;
	printf("%d\n", a);
	return 0;
}

在这里插入图片描述

2.2:指针变量的大小

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	printf("%d\n", sizeof(int*));
	printf("%d\n", sizeof(char*));
	printf("%d\n", sizeof(short*));
	printf("%d\n", sizeof(double*));
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  1. 32位平台下地址是32个bit位,指针变量大小是4个字节
  2. 64位平台下地址是64个bit位,指针变量大小是8个字节
  3. 注意指针变量的大小和类型是无关的,只要是指针类型的变量,在相同的平台下,大小都是一样的.

3:指针变量类型的意义

代码1

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 10;
	int* pa = &a;
	*pa = 20;
	return 0;
}

解引用修改前

在这里插入图片描述

解引用修改后

在这里插入图片描述

代码2

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 0x11223344;
	char* pa = &a;
	*pa = 20;
	return 0;
}

解引用修改前

在这里插入图片描述

解引用修改后

在这里插入图片描述

1:char * 类型的指针解引用访问1个字节.
2:short * 类型的指针解引用访问2个字节.
3:int * 类型的指针解引用访问4个字节.
4:double*类型的指针解引用访问8个字节.

4:const修饰指针

4.1:const修饰变量

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 20;
	a = 30;
	const int b = 25;
	//b不可被修改
	b = 0;
	return 0;
}

在这里插入图片描述

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	const int b = 25;
	int* pb = &b;
	printf("b = %d\n", b);
	*pb = 30;
	printf("b = %d\n", b);
	return 0;
} 

在这里插入图片描述

4.2:const修饰指针变量

博主将通过以下几段代码来讲解const修饰指针变量,首先来看代码1.

代码1

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void test1()
{
	int n = 10;
	int m = 20;
	int* p = &n;
	*p = 20;
	p = &m; 
}

int main()
{
	test1();
	return 0;
} 

在这里插入图片描述

代码2(const放在*左边)

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void test2()
{
	int n = 10;
	int m = 20;
	const int* p = &n;
	*p = 20;
	p = &m; 
}

int main()
{
	test2();
	return 0;
} 

在这里插入图片描述

代码3(const放在*右边)

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void test3()
{
	int n = 10;
	int m = 20;
	int* const p = &n;
	*p = 20;
	p = &m; 
}

int main()
{
	test3();
	return 0;
} 

在这里插入图片描述

代码4(const放在*左右两边)

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void test4()
{
	int n = 10;
	int m = 20;
	const int* const p = &n;
	*p = 20;
	p = &m; 
}

int main()
{
	test4();
	return 0;
} 

在这里插入图片描述

通过对比上面四段代码,我们可以得出以下结论

  1. const如果放在 * 的左边,修饰的是指针变量所指向的内容,此时无法通过指针改变指针所指向的内容,但是指针本身的内容可以改变.
  2. const如果放在 * 的右边,修饰的是指针变量本身,此时无法改变指针本身的内容,但是指针所指向的内容可以通过指针对其进行改变.
  3. const如果既在 * 的左边,又在 * 的右边,此时既修饰指针变量本身,又修饰指针变量所指向的内容,因此,既不能够通过指针改变指针变量所指向的内容,又不能够改变指针本身的内容.

5:指针运算

5.1:指针加减整数

代码1

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int n = 10;
	char* p1 = (char *) & n;
	int* p2 = &n;

	printf("&n     = %p\n", &n);

	printf("\n");

	printf("p1     = %p\n", p1);
	printf("p1 + 1 = %p\n", p1 + 1);

	printf("\n");

	printf("p2     = %p\n", p2);
	printf("p2 + 1 = %p\n", p2 + 1);
	return 0;
} 

在这里插入图片描述

代码2

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//求出数组元素的大小
	int sz = sizeof(arr) / sizeof(arr[0]);

	int* p = arr;
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
} 

在这里插入图片描述

5.2:指针-指针

代码1

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%d\n", &arr[9] - &arr[0]);
	printf("%d\n", &arr[0] - &arr[9]);
	return 0;
}

在这里插入图片描述

字符串的结束标志是\0,而strlen函数是用于统计\0之前的字符个数.

代码2

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int mystrlen(char * str)
{
	char* begin = str;
	while (*str != '\0')
	{
		str++;
	}
	return str - begin;
}

int main()
{
	char arr[100] = "0";
	scanf("%s", arr);
	int result = mystrlen(arr);
	printf("%d\n", result);
	return 0;
}

在这里插入图片描述

在这里插入图片描述

5.3:指针的关系运算

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	//指针的大小比较
	while (p < arr + sz)
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述

6:野指针

6.1:野指针成因

6.1.1:指针未初始化

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	//局部变量指针未初始化,默认为随机值
	int* p;
	*p = 20;
	return 0;
}

在这里插入图片描述

6.1.2:指针越界访问

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	for (int i = 0; i < 11; i++)
	{
		*p = i;
		p++;
	}
	return 0;
}

6.1.3:指针指向的空间释放

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int * test()
{
	int n = 25;
	return &n;
}

int main()
{
	int* p = test();
	printf("%d\n", *p);
	return 0;
}

在这里插入图片描述

6.2:如何规避野指针

学习了野指针的成因以后,那么该如何去避免野指针呢?有以下几种方式。

6.2.1:指针初始化

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int n = 25;
	int* p1 = &n;
	int* p2 = NULL;
	return 0;
}

6.2.2:小心指针越界

一个程序向内存申请了哪些空间,通过指针也只能访问所对应的空间,不能够超出访问,超出了就是越界访问.

6.2.3:指针变量不再使用时,及时置NULL,指针使用之前检查有效性

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	for (int i = 0; i < 10; i++)
	{
		//虽然后置++的优先级高于解引用操作符,但是由于是先使用再++,因此一开始对p解引用得到是数值为1的元素.
		*p++ = i;
	}
	p = NULL;

	return 0;
}

6.2.4:避免返回局部空间的地址

野指针成因的第三个例子.

7:二级指针

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int n = 25;
	int a = 20;
	int* p = &n;
	int** pp = &p;
	printf("&n  = %p\n", &n);
	printf("*pp = %p\n", *pp);
	//等价于 p = &a;
	*pp = &a;
	//等价于 a = 30
	**pp = 30;
	printf("&a  = %p\n", &a);
	printf("*pp = %p\n", *pp);
	printf("%d\n", **pp);
	printf("a = %d\n", a);
	return 0;
}


在这里插入图片描述
在这里插入图片描述

8:指针数组

8.1:语法

int * 数组名[元素个数]
Eg:int * arr[5]

8.2:指针数组模拟实现二维数组

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int arr1[5] = {1,2,3,4,5};
	int arr2[5] = {6,7,8,9,10};
	int arr3[5] = {11,12,13,14,15};
	int* parr[3] = { arr1,arr2,arr3 };
	int Sz = sizeof(parr) / sizeof(parr[0]);
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	for (int i = 0; i < Sz; i++)
	{
		for (int j = 0; j < sz; j++)
		{
			printf("%2d ", parr[i][j]);
			//printf("%2d ", (*(arr + i))[j]);
		}

		printf("\n");
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述

9:assert断言

讲完了指针相关的基础知识后,接下来博主将为大家介绍assert断言

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
int main()
{
	int* p = NULL;
	assert(p != NULL);
	return 0;
}

在这里插入图片描述

assert()的使用对程序员是非常友好的,使用assert有以下几个好处:

  1. 能自动标识文件和出问题的行号.
  2. 无需更改代码就能开启或关闭assert()的机制。
#define  _CRT_SECURE_NO_WARNINGS
#define NDEBUG
#include <assert.h>
int main()
{
	int* p = NULL;
	assert(p != NULL);
	return 0;
}

在这里插入图片描述

好啦,家人们,关于指针初阶这块的相关细节知识,博主就讲到这里了,如果uu们觉得博主讲的不错的话,请动动你们滴滴给博主点个赞,你们滴鼓励将成为博主源源不断滴动力!

举报

相关推荐

0 条评论