Day 16 指针的分类 指针和变量的关系 字节序 指针的运算

1. 指针的分类

按照指针指向的数据类型进行分类

可分为字符型指针、短整型指针、整形指针、长整型指针、浮点型指针、double型指针

char ch = 'y';
char *pch = &ch;//字符型指针

short s = 10;
short *ps = &s;//短型指针

int a = 10;
int *pa = &a;//整型指针

long long l = 10;
long long *pl = &l;//长整型指针

float f = 10;
float *pf = &f;//浮点型指针

double d = 10;
double *pd = &d; //double型指针

函数指针,本质是一个指针,是指向函数的指针

指针函数,本质是一个函数,函数的返回值是一个指针

结构体指针,本质是一个指针,指向一个结构体的指针

指针的指针,是指向指针的指针,是一个二级指针

数组指针,本质是一个指针,表示指向数组的指针

指针数组,本质是一个数组,数组中的每一个元素都是指针

指针地址的自增自减和数据类型有关,该指针的数据类型是什么,增加的地址量就是该数据类型的大小的个数

2. 指针和变量的关系

指针可以存放变量的地址编号,之前不能用函数将两个数交换,学了指针就完成这一工作

#include<stdio.h>

int swap(int *pa, int *pb);

int main()
{
	int a = 10;
	int b = 20;
	printf("交换前%d, %d\n", a, b);
	swap(&a, &b);
	printf("交换后%d, %d\n", a, b);

	return 0; 
}

int swap(int *pa, int *pb)
{
	int temp;
	temp = *pa;
	*pa = *pb;
	*pb = temp;
	return 0;	
} 

函数的形参传不回来,但是指针可以一直指向那个值,并传递回来

 3. 字节序

字节序,又称端序或尾序,在计算机领域中,指电脑内存中或在数字通信链路中,占用多个字节的数据字节排列顺序

字节的排列方式又两种:大端序,小端序

大端序是指将数据的低位放在内存的高地址位,高位放在低位,这种方式就相当于从上至下将数据的位序顺序存储,而小端序和这个正好相反

我们可以测试电脑是大端序还是小端序

#include<stdio.h>

int main()
{
	int a = 0x12345678;
	int b = 0x78563412;
	
	short *pa, *pb;
	pa = (short *)&a;
	pb = (short *)&b;
	
	printf("%p, %p\n", &pa, &pb);
	printf("%x, %x\n", *pa, *pb);
	
	*pa++;
	*pb++;
	
	printf("%p, %p\n", &pa, &pb);
	printf("%x, %x\n", *pa, *pb);
	
	 
	
	return 0;
}

 可以看出我的电脑是大端序

注:

*p的取值,由指针类型所决定,例如字符型就是一个字节

p++指向下一个对应类型的数据

4. 指针与数组元素之间的关系

指针可以指向数组的数组名,意为指向数组的第一个值的地址

int a[10];
int *p = a;

其实数组名也是一个地址(指针),在后面可以和p代换

	for(int i = 0; i < 10; i++)
	{
		printf("%d\n", a[i]);
		printf("%d\n", p[i]);
		printf("%d\n", *(a + i));
		printf("%d\n", *(p + i));//取值 

		printf("%p\n", &a[i]);
		printf("%p\n", &p[i]);
		printf("%p\n", a + i);
		printf("%p\n", p + i);//取地址
		 
	}

我们遍历一个数组的时候,a[i]和p[i]都代表数组中第i个元素,*(p + i),*(a + i)代表数组的后i个元素,也可以将值输出出来,取地址,和这个也类似

但要注意的是p和a是有不同的,p是一个指针变量,而a是一个常量,a不可以赋值,但是可以给p赋值

练习:通过swap函数和指针,将输入的三个数,从小到大输出

#include<stdio.h>

float swap(float *pa, float *pb)
{
	float temp;
	temp = *pa;
	*pa = *pb;
	*pb = temp;
	return 0;		
}

int main()
{
	float a, b, c;
	
	
	printf("请输入三个小数:\n");
	scanf("%f%f%f", &a, &b, &c);
	
	if(a > b)
	{
		swap(&a, &b);
		if(b > c)
		{
			swap(&b, &c);	
		}
		if(a > b)
		{
			swap(&a, &b);	
		}	
	}
	else
	{
		if(b > c)
		{
			swap(&b, &c);	
		}
		if(a > b)
		{
			swap(&a, &b);	
		}	
	}
	printf("a = %.1f, b = %.1f, c = %.1f", a, b, c); 
	
	
	return 0;
}

和之前做过比大小输出的类似,这回直接用swap函数将两个值替换,发现有个函数,代码量是真的会减少很多

5. 指针的运算

指针是可以加一个整数的,意为指向这个整数后的元素,结果还是个地址变量

但是一般这么做是没有什么意义的,只有在数组中加一个整数才有一个实际意义

指针也可以比较大小,但也是在数组中才有意义

两个指针也可以相互赋值,但是必须是两个类型相同的指针

6. 指针数组和数组指针

指针数组是一个存放指针的数组,其实可以用来和一个数组一一对应,然后用指针来操作数组

#include<stdio.h>

int main()
{
	int *arr[5] = {NULL};
	
	int brr[5] = {4396, 4936, 4399, 4639, 4369};
	
	for(int i = 0; i < 5; i++)
	{
		arr[i] = &brr[i];
		printf("%p\n", arr[i]);
		printf("%d\n", *arr[i]);
	}
	
	
	
	return 0;	

可已通过指针数组来将brr数组的值全部输出

数组指针本质上是一个指针,他可以指向一个二维数组,他后面跟的是这个二维数组的列,行是根据这个二维数组的变化而变化

#include<stdio.h>

int main()
{
	//数组指针,指向一个数组的指针 
	int (*parr)[5] = {0};
	int arr[3][5] = {{1, 2, 3, 4, 5}, 
					 {6, 7, 8, 9, 10},	
					 {11, 12, 13, 14, 15}};
	parr = arr;
	for(int i = 0; i < 3; i++)
	{
		for(int j = 0; j < 5; j++)
		{
			printf("%d	", parr[i][j]);
		}
		printf("\n");
	}
	
	
	return 0;
}

总结:

今天算是真正开始学习指针,还是有些绕,特别是指针的运算刚开始有些绕不清,但是后面慢慢熟悉了以后,就能看懂了,我觉得有了指针,就能更好地使用函数以及对数组操作

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,由于时间限制和技术限制,我无法为您提供完整的代码。但是,我可以向您解释一下如何使用二维数组和指针数组来实现日历。 首先,我们需要一个二维数组来存储每个月的天数和每个月的第一天是星期几。例如,我们可以定义一个名为calendar的数组,它包含12行和2列。第一列存储每个月的天数,第二列存储每个月的第一天是星期几。 ```c int calendar[12][2] = { {31, 2}, // January {28, 5}, // February {31, 5}, // March {30, 1}, // April {31, 3}, // May {30, 6}, // June {31, 1}, // July {31, 4}, // August {30, 0}, // September {31, 2}, // October {30, 5}, // November {31, 0} // December }; ``` 接下来,我们需要一个指针数组来存储每个月的日历。我们可以定义一个名为month的指针数组,它包含12个指向int类型的指针。每个指针都指向一个包含每个月日历的二维数组。 ```c int* month[12]; ``` 然后,我们可以使用一个for循环来创建每个月的日历。在每个月的循环中,我们需要使用malloc函数动态分配一个二维数组,然后使用for循环填充日历。 ```c for (int i = 0; i < 12; i++) { int days = calendar[i][0]; int first_day = calendar[i][1]; int week_day = 0; month[i] = (int*)malloc(6 * 7 * sizeof(int)); for (int j = 0; j < 6 * 7; j++) { if (j < first_day || j >= first_day + days) { month[i][j] = 0; } else { month[i][j] = j - first_day + 1; } } } ``` 最后,我们可以使用另一个for循环来打印整个日历。在每个月的循环中,我们需要使用for循环打印日历的表头和每一天的日期。 ```c for (int i = 0; i < 12; i++) { printf("%d月\n", i + 1); printf("日 一 二 三 四 五 六\n"); int days = calendar[i][0]; int first_day = calendar[i][1]; int week_day = 0; for (int j = 0; j < 6 * 7; j++) { if (j < first_day || j >= first_day + days) { printf(" "); } else { printf("%2d ", month[i][j]); } week_day++; if (week_day == 7) { printf("\n"); week_day = 0; } } printf("\n"); } ``` 这就是如何使用二维数组和指针数组来实现日历的基本过程。当然,这只是一个简单的例子,您可以根据自己的需求和喜好进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值