一文带你彻底了解指针,这可能是全网讲得最透彻最简单的方法(ubunqu出品必是精品),记得看注释

9 篇文章 0 订阅
2 篇文章 0 订阅

1 指针的概念

指针就是地址 ,就是编号
指针变量就是保持地址的变量
32位系统下,指针变量的大小是4字节
在这里插入图片描述

2 指针的定义和使用

#include  <stdio.h>
int main()
{
	int a = 10;
	//需求 定义一个指针变量来保存 a的地址
	//ubunqu指针定义3步骤
	//1.需要保存谁的地址 将其定义形式放在此处
	//2.定义一个 *和符号结合
	//3.使用*和符号替换掉定义形式里面的变量名或数组名或函数名
	//1. int a  2. *p  3.int *p
	int *p = &a;
	//ubunqu指针分析3步骤
	//1 只要在定义处看到符号和*结合,这个符号一定是一个指针变量
	//2 指针变量的类型  将符号拖黑剩下的类型 int *
	//3 指针变量保存什么数据类型的地址 将符号和符号最近的一个*拖黑剩下的类型

	//指针的使用 在使用时 对指针变量取* 得到的是取这个指针变量指向那块内存空间的值
	printf("%d\n",*p);
	*p = 100;
	printf("%d\n", *p);
	printf("%d   %d\n", sizeof(p), sizeof(int *));
	return 0;
}

注意:
在使用时 对一个表达式取& 会使这个表达式的类型 加一级*
在使用时 对一个表达式取* 会使这个表达式的类型 减一级*

3 指针的步长

宽度: 取指针变量指向空间的内容 取的字节数
步长 :指针变量加1 跨过的字节数
宽度== 步长
步长 = sizeof( 将符号和符号最近的
拖黑剩下的类型)
在这里插入图片描述

int main()
{
	int  num = 0x01020304;
	int *p1 = &num;
	short *p2 = (short*)&num;
	char *p3 = (char* )&num;
	printf("%x  %x  %x\n",*p1,*p2,*p3);
	return 0;
}

4 多级指针

int *P
int **P
int **p
对于普通指针,定义的指针类型只需要比需要保存的数据的类型多一级

int  main()
{
	int  a = 10;
	int  *p = &a;
	// int  *p    ;    *q    ;  int  **q
	int  **q = &p;
	//int  **q  ; *k  ; int  **(*k)
	int ***k = &q;
	int ****j = &k;

	int  ***********************n = NULL;
	int ************************m = &n;
	printf("%d %d %d\n",*p,**q,***k);

	return  0;
}

在这里插入图片描述

5 野指针

未初始化的指针,不能直接使用,指向是随机的,未知的

int  main()
{
	//野指针 - 未初始化的指针
	//int  a = 10;
	int  *p ;// p的指向是随机的 指向的内存也是随机的
	//int  *p = (int *)0x1000;  指针保存的地址 一定是合法的(向系统申请过空间返回的地址)
	printf("%d\n",*p);
	*p = 100;
	printf("%d\n", *p);
	return 0;
}

5 空指针
空指针: 指针被赋值为NULL
作用是作为一个标志
定义指针是赋值为NULL
使用时不为NULL
使用结束后,赋值为NULL
通过判断指针是否为NULL ,这个指针是否还在使用

int  main()
{
	//野指针 - 未初始化的指针
	//#define  NULL  0x00
	int  *p = NULL;// 用来作为一个标志  如果这个指针等于NULL 代表没有被使用

	printf("%d\n",*p);//error
	*p = 100;//error
	printf("%d\n", *p);//error
	return 0;
}

6 万能指针

void* 可以保存任意类型的地址

int  main()
{

	int  a = 10;
	char b = 20;
	short c = 30;
	//int *p =&a;
	//short *q = &c;
	//char *k = &b;
	void * p1 = &a;//int *
	void * p2 = &b;//char*
	void * p3 = &c;//short*
	//void x;  不可以定义

	*(int*)p1 = 200; // *p1  宽度  sizeof(void)
	* (char*)p2 = 10;

	return 0;
}

7 const修饰的指针

const int *p == int const *p
不能修改p指向那块空间的内容 p本身的值可以改变,
int * const p ;
不能更改p指针变量本身的值 ,但是可以修改p指向那块空间的内容
const int * const p
不能修改p指向那块空间的内容,不能更改p指针变量本身的值

int main()
{
	int   a = 10;
	int b = 0;
	//const int b;
	//const int   *p == int const  *p
	// int   * const p;
	 int const  * const p = &a;
	//不能通过*p去修改p指向那块空间的内容
	//*p = 1000; error
	//p = &b;
	return 0;
}

8 指针修改实参的值-指针作为形参

想在一个函数中修改实参的值,实参必须传地址

void swap(int *x, int *y)
{
	int  tmp = *x;
	*x = *y;
	*y = tmp;
}
int  main()
{
	int  a = 10; 
	int b = 20;
	swap(&a,&b);
	printf("a=%d b=%d\n",a,b);
	return 0;
}

在这里插入图片描述

9 指针与数组的使用

定义一个指针变量保存数组首元素地址,既可以访问数组的每一个元素
在这里插入图片描述

int  main()
{
	int  a[5] = { 1,2,3,4,5 };
	int *p = a;
	for (int i = 0; i < 5; i++)
	{
		//printf("%d ",a[i]);
		printf("%d ", *(a+i));
		//printf("%d ", *(p+i));
		//printf("%d ", p[i]); // A[i] == *(A+i)
	}
	return 0;
}

10 数组作为函数形参会被退化为指针

// void  print_array(int  x[5])
// void  print_array(int  x[50000])
 void  print_array(int  *x,int  n)
{
	for (int i = 0; i < n; i++)
	{
		//printf("%d ",*(x+i));
		printf("%d ", x[i]);
	}
}
int  main()
{
	int  a[5] = { 1,2,3,4,5 };
	print_array(a,sizeof(a)/sizeof(a[0]));
	return 0;
}

11 指针数组

指针数组 : 本质是一个 数组 ,数组的每一个元素是指针
整型数组

int  main()
{
	int a = 0;
	int b = 1;
	int  c = 2;
	int * p[3] = {&a,&b,&c};//定义了一个数组 数组有3个元素 ,每个元素int*类型
	/*for (int i = 0; i < 3; i++)
	{
		printf("%d ",*p[i]);
	}*/
	int  **q = p;
	for (int i = 0; i < 3; i++)
	{
		//printf("%d ", *(*(q+i)));
		printf("%d ", *q[i]);
	}

	return 0;
}

在这里插入图片描述

12 数组指针

本质是一个指针,指针变量保存一个数组的地址

int  main()
{
	int a[5] = { 1,2,3,4,5 };
	//&a
	// int a[5]; *p ; int (*p)[5]
	int(*p)[5] = &a;
	// 指针的类型 int(*)[5]   ; 保存的数据 int[5]的地址
	printf("%d ",sizeof(p));
	printf("%u  %u\n",p,p+1);//sizeof(int[5] ) 
	//通过数组指针可不可以访问数组的每一个元素? 
	//* p 特殊: 对数组指针取* 不是得到整个数组的内容,而是得到首元素地址
	//如果将p看成一个行地址 对行地址取* 得到的是该行的第0列的地址
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", *(*p + i));
	}
	return 0;
}

13 数组指针在二维数组中使用

int   main()
{
	int  a[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
	//int [4]
	int(*p)[4] = a;
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		for (int j = 0; j < sizeof(a[0]) / sizeof(a[0][0]); j++)
		{
			//printf("%d ", *(*(p + i) + j));
			printf("%d ", p[i][j]);
		}
		printf("\n");
	}


	return 0;
}

在这里插入图片描述

14 指针的运算

相同类型的两指针相减得到的是两个指针之间的步长数
指针不可以做相加运算
指针可以比较 p == q p>q

在这里插入图片描述

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
LVS(Linux Virtual Server)是一种基于 Linux 系统的负载均衡集群技术,它主要用于将网络流量分发到多个服务器上,以提高系统的可靠性、可扩展性和性能。 LVS 集群一般包括四个组件:调度器(LVS 调度器)、前端服务器(负载均衡器)、后端服务器(真实服务器)和存储服务器(用于共享数据)。首先,调度器接收来自客户端的请求,然后根据配置的调度算法(如轮询、加权轮询、最小连接数等)将请求分发到多个前端服务器。前端服务器接收到请求后,通过相应的负载均衡算法将请求转发到后端的真实服务器上进行处理。在整个过程中,存储服务器用于存放共享的数据,以确保所有的真实服务器都能获取到相同的数据,并提供一致的服务。 LVS 集群的优点是能够提高网站的稳定性和可靠性,当某一台服务器出现故障时,调度器会自动将请求分发到其他可用的服务器上,从而保证服务的连续性。同时,LVS 集群还能够通过增加前端服务器和后端服务器的数量来提高系统的性能和吞吐量,以满足不断增长的用户需求。 在实际应用中,LVS 集群需要合理配置,包括选择合适的调度算法、调整每台服务器的权重、选择适当的硬件设备等。此外,还需要及时监控集群的运行状态,及时发现和解决故障,以确保整个系统的正常运行。 总的来说,LVS 负载均衡集群是一种强大而高效的集群技术,能够帮助企业提高系统的可靠性和性能,是现代互联网应用中不可或缺的重要组成部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔动山霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值