Day13 记录

本文详细讲解了C语言中的数组指针概念、二维数组的访问与操作、动态内存分配的malloc函数应用,以及如何通过指针函数和快速排序算法提高代码效率。
摘要由CSDN通过智能技术生成

目录

易混淆:

10.7 数组指针

10.7.1 概念语法形式

10.8 二维数组

10.8.1 访问形式

10.8.2 指针方式实现遍历打印

​编辑

10.8.3 指针方式实现二维数组边缘元素的求和

10.8.4按行逆序

10.9 malloc函数 动态内存分配

10.9.1 斐波拉契数组前十项存储

10.10 指针函数

10.10.1 快速排序


易混淆:

1.

2.

3.

字符型指针可以是数组的数组名,也可以是字符串常量。

指针变量来代替匿名数组的实例。

10.7 数组指针

10.7.1 概念语法形式

指向整个数组的指针。

int a[10] = {1,2,3,4,5,6,7,8,9,0}
int *p;
p = &a

这样是不行的,指针变量p所存放的只能是基类型int型的地址,而a是数组a首元素的地址。&a的基类型为长度为10的一维整型数组。

改正方法:int(*p)[10];*的出现仅仅是说明p是一个指针。去掉变量名剩下类型名,此时定义了一个长度为10的一维整型数组指针。


这种写法与指针数组语义冲突。此处是一次性定义了十个int *型的指针。

p + 1 => p + 1*sizeof(基类型) 。

上述过程中p的基类型是长度为10的一维整型数组,故sizeof(基类型) = 40字节。

10.8 二维数组

二维数组作为函数参数传递,形参是指向数组的指针。

10.8.1 访问形式

int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
//a<=> &a[0] 长度为4的一维整型数组的地址

int (*p)[4] //指向元素为长度为4 的一维整型数组   此时指针变量p为野指针

int (*p)[4] = NULL      //防止野指针 先把指针变量置零
p = a;
printf("%d\n", *((int *)(a + 3) - 3));       //输出的为10

p += 1;  =>p = p + sizeof(基类型) => p = p + 16字节, 故p指向的位置向后移动16个字节。

*(p+1) <=> p[1]    相当于a当中第二个一维数组的数组名,数据类型为 int *型。

*(p + 1) + 2    是*(p + 1)向后偏移8个字节。

*(*(p + 1) + 2)    是*(p + 1) + 2 所指向数组中对应位置的值。 

10.8.2 指针方式实现遍历打印

void printArray2D(int (*a)[4], int rows)
{
	int i, j;
	for(i = 0;i < rows;++i)
	{
		for(j = 0;j < 4;++j)
		{
			printf("%2d ", *(*(a + i) + j));
		}
		puts("");
	}
}

*(p + i)是整型指针 ,+j是整形指针向后偏移,再在外整体加* ,*(*(a+i) + j)取该指针所指向的值。

10.8.3 指针方式实现二维数组边缘元素的求和

int acrossArray2D(int (*a)[4], int rows)
{
	int i, j;
	int sum = 0;
	for(i = 0;i < rows;++i)
	{
		for(j = 0;j < 4;j++)
		{
			if(i == 0 || i == rows - 1 || j == 0 || j == 3)
			{
				sum += *(*(a+i) + j);
			}
		}
	}
	return sum;
}

与之前所学运算内容区别在于:先找到*(a+i)行的地址,再*(a+i)+j找到具体位置,通过*进行指针运算

10.8.4按行逆序

void swap(int *begin, int *end)
{
	int t = *begin;
	*begin = *end;
	*end = t;
}
void reverse(int *begin, int *end)
{
	while(begin < end)
	{                                             //迭代
		swap(begin++,end--);
	}
}
void reverse2D(int (*a)[4], int rows)
{
	int i;
	for(i = 0;i < rows;++i)
	{
		reverse(*(a + i),*(a + i) + 3);        //传进reverse函数形参中的是该行首元素的地址 
                                                  和该行末尾元素的地址
	}
}

10.9 malloc函数 动态内存分配

void *malloc(size_t size) 返回值是指针的函数.

size_t size是传你想要的空间的大小。malloc函数会把这段空间的首地址传递给你。并向你保证它肯定是连续的。这段空间被分配在堆区。

调用过程:

分配 ->使用->销毁->置空

10.9.1 斐波拉契数组前十项存储

int fib(int n)
{
	if(1 == n || 2 == n)
	{
		return 1;
	}
	else
	{
		return fib(n - 1) + fib(n - 2);
	}
}
int main(void)
{
	int n = 10;
	int *p = malloc(n * sizeof(int));
	int i;
	if(p != NULL)
	{
		for(i = 0;i < n;++i)
		{
			*(p + i) = fib(i + 1);
		}
		for(i = 0;i < n;++i)
		{
			printf("%d\n", *(p + i));
		}
		free(p);

		p = NULL;
	}
}

若想重新申请空间 则新申请的空间与原来申请的空间不会连续。需要把原来空间上存储的内容拷贝到新空间中。

int main(void)
{
	int n = 5;
	int *p = malloc(n * sizeof(int));
	int i;
	for(i = 0;i < n;++i)
	{
		*(p + i) = fib(i + 1);	
	}
	int m = 20;
	int *q = malloc(m * sizeof(int));
	memcpy(q, p, n * sizeof(int));
	free(p);
	p = q;
	for(i = n;i < m;i++)
	{
		*(q + i) = fib(i + 1);
	}
	for(i = 0;i < m;++i)
	{
		printf("%d\n", *(p + i));
	}
	free(p);
	p = q = NULL;
}

但是这个过程不需要我们自行编写,只需要理解思路即可。

p = realloc(p, m * sizeof(int));

10.10 指针函数

返回值为指针的函数,绝不能返回局部变量地址,返回static修饰的静态局部变量,全局变量或者是你传进去的变量地址可以。

什么是函数的地址?

函数有汇编语句组成,函数的函数名即为函数的入口地址。

int *p;

p = add;不行的,基类型不同,add是函数add函数的入口地址,p是指向整型变量的指针。

怎么定义一个指针变量,可以存储一个函数的地址?

int (*p)(int a, int b)                               

说明指针变量p指向一类函数(由两个整型作为参数,返回值是整型)

指向 void fn(void)不行。

此时指针变量是野指针。

p = add; 此时这样赋值就可以啦。类型匹配

实例:

int div3(int n)
{
	return n % 3 == 0;
}
int div5(int n)
{
	return n % 5 == 0;
}
void printArray(int *a, int len, int (*pfn)(int))
{
	int i;
	for(i = 0;i < len;++i)
	{
		if(pfn(a[i]) != 0)
		{
			printf("%d\n", a[i]);
		}
	}
}

可以降低函数的耦合性,解耦合运算。

10.10.1 快速排序

qsort(目标,目标元素个数,目标所占的字节数,比较函数(决定排序方式是升序还是降序))

int shortcmp(const void *p1, const void *p2)
{
	short *q1 = (short *)p1;
	short *q2 = (short *)p2;

	if(*q1 > *q2)
	{
		return 1;
	}
	else if(*q1 == *q2)
	{
		return 0;
	}
	else
	{
		return -1;
	}
}
int main(void)
{
	short a[] = {1,2,-3,4,-5,6,7,8,9,10,24};
	int len = sizeof(a) / sizeof(*a);
//	printArray(a, len, div3);
//	printArray(a, len, div5);

	qsort(a, len, sizeof(*a), shortcmp);
	int i;
	for(i = 0;i < len;++i)
	{
		printf("%d\n", a[i]);
	}

	return 0;

}

  • 40
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值