嵌入式学习C语言(十五)指针函数 动态内存分配 函数指针 指针数组 指针指针

目录

一、指针函数

二、动态内存分配

        malloc函数

        free函数

         realloc函数

        calloc函数

        reallocarray函数

三、函数指针

        qsort函数 

四、指针数组

五、指针的指针

六、两句话技巧


一、指针函数

        1.返回值为指针的函数,不能返回局部变量的地址,全局变量、静态变量与传进去的指针地址均可返。

二、动态内存分配

        malloc函数

        1.  void *malloc(size_t  size);

        2.size_t  <==>  unsigned long  ,size 表示申请的空间的大小,单位字节。

        3.返回值:成功返回申请到内存空间的地址;失败返回 NULL。

        4.#include

        5.去堆上申请一段连续的空间。返回的是一个指针,指向申请的内存空间(内存空间未初始化全是随机数)。

        6.使用该函数后要判断内存空间是否申请到,申请空间申请不到会返回空指针。

        7.用完要释放空间。

        free函数

        1.  void free(void *ptr);

        2.释放之前申请的堆上的空间 。

        3.ptr 一定是之前申请到堆上空间的地址 。

eg   拼接字符串:先申请一个内存空间存放“Hello”字符串,再申请一个内存空间把“Hello”先放进去再把字符串“World!”拼接在后面,释放掉第一次申请的内存空间,输出拼接的字符串后释放掉第二次申请的内存空间。

int main(void)

{

     const char *s ={"Hello"};

     const char  *t ={"World"};

     char * p= malloc(strlen(s) + 1);    //因为隐含'\0'

     if(p != NULL)                                  //说明空间申请成功

     {

             strcpy(p,s);                             //字符串拷入堆中。

             char *q = malloc(strlen(q) + strlen(t) +1); //重新申请空间,使大小够装下新的 
             strcpy(q,p);                              

             strcat(q,t) ;  //进行拼接

             free(p);      //释放p指向的堆空间,p变成野指针

             p = q;         // 不让p变成野指针

             puts(q);     //打印字符串

     }

        free(q);   //释放p和q指向的堆空间

        return 0;

}

         realloc函数

        1.void *realloc(void *ptr,size_t size);                

        2.void *ptr是原来空间的地址;size_t size是新开多大的空间;

        3.把原来空间的内容拷过来并释放原来的空间,可扩大可缩小。

eg   

int main(void)
{
	const char *s = "Hello";
	const char *t = "World!";
	char *p = malloc(strlen(s) + 1);

	if(p != NULL)
	{
		strcpy(p, s);
		puts(p);
		
		p = realloc(p, strlen(p) + strlen(t) + 1);
		strcat(p, t);
		puts(p);
	}

	free(p);
	return 0;
}

        calloc函数

        1.void *calloc(size_t   nmemb, size_t  size);

        2.申请空间numemb * size 个字节,分几块,每块几个字节。

        reallocarray函数

        1.一般形式:void *reallocarray(void *ptr, size_t nmemb, size_t size);

三、函数指针

        1.指向函数类型的指针,指向一类函数。 int (*p) (int , int);

        2.函数的函数名  函数的第一条语句  均为函数的入口地址

        3.函数指针的形式要与回调函数的形式相同,参数可以只写个类型。

int  add(int a,int b)

{

        return a + b;

}

int sub(int a,int b)

{

        return a - b;

}

int main(void)

{

        int a = 10;

        int b = 20;

        int(*p)(int a,int b) ; //  函数指针,未赋值的野指针

        p = add;           // 将add函数的入口地址赋值给p

        p(a,b);               //间接调用函数

        (*p)(a,b);           //两种写法都可调用函数

        return 0;

}

        4.回调函数 

        通过函数指针在函数的参数中调用函数,将一个函数作为参数传递给另一个函数,当特定事件发生或条件满足时,接收参数的函数会调用这个传入的函数

int pow2(int n)   //返回该数的平方

{

        return n * n;

int fn(int n)   //返回该数本身

{

        return n;

}

void sort(int *a,int len,int(*pfn)(int))     //第三个参数用来说明,你要比较  数的平方  还是其本身

{                                                           //  甚至可以继续扩展,只要函数返回值为int型,且形参

        int i,j;                                            // 只有 一个int型

        for(i = 0;i < len - 1;++i)

        {

                for(j = i + 1;j < len;++j)

                {

                        if(pfn(a[i]) > pfn(a[j]))  //调用的函数比较

                        {

                                int t = a[i];

                                a[i] = a[j];

                                a[j]  = t;

                        }

                }

        }

}   //这是一个选择排序函数

int main(void)

{

        int a[] = {8,9,-5,1,4,3,2};

        int len =sizeof(a);

        sort(a,len,pow2);  //根据需求按他的平方大小排序。

        return 0;

}

        qsort函数 

        1.void qsort(void *base, size_t nmemb, size_t size,
                  int (*compar)(const void *, const void *));

        2. int (*compar)(const void *, const void *))是一个函数指针。

eg    调用qsort函数

int doublecmp(const void *p1, const void *p2)
{
	double *q1 = (double *)p1;
	double *q2 = (double *)p2;

	if(*q1 > *q2)
	{
		return 1;
	}
	else if(*q1 == *q2)
	{
		return 0;
	}
	else
	{
		return -1;
	}
}
int main()
{
	double a[] ={1,2,3,4,5,6,7,8,9,0};
	int len = sizeof (a) /sizeof(*a);
	qsort(a,sizeof(a) / sizeof(*a) , sizeof(*a),doublecmp);
	int i;
	for (i=0; i< len ; ++i)
	{
		printf("lf\n",a[i]);
	}
}

eg 立即跳转到0x30001000地址处

void (*pfn)(void)
pfn = (void (*)(void)) 0x30001000 ;
pfn();

四、指针数组

        1.int  *a[10];   定义了一个数组,有10个指针(共占80个字节)

  eg1    打印字符串

void printfStrings(char *s[], int len)
{
	int i;
	for (i= 0;i < len; ++i)
	{
		puts(s[i]);
	}
}
int main()
{
	char *s[3] ={"Hello","World","China"};     //s[0]存着"Hello"的地址,类推
	int len = sizeof(s) / sizeof (*s);
	printfStrings(s,len);
	return 0;
}

 eg2   找最大值

char *maxOfStrings(char *s[], int len)
{
	char *max;
	max = s[0];
	int i;
	for(i = 1;i < len;++i)
	{
		if(strcmp(max, s[i]) < 0)
		{
			max = s[i];
		}
	}
	return max;
}

五、指针的指针

        1.指向指针的指针。

void getMemory(char *p)
{
   p = malloc(100);
}
int main(void)
{
	char *s;
    getMemory(s);//s指针未指向malloc申请的100个字节
    strcpy(s, "Hello");//此行代码崩溃,s为野指针(随机数)
	puts(s);
}
void getMemory(char **p)//  char * 是p的基类型,后边一个*是类型说明符。指向指针的指针
{
   p = malloc(100);
}
int main(void)
{
	char *s;
    getMemory(&s);
    strcpy(s, "Hello");
	puts(s);
}

 eg1  找最大值

char *maxOfStrings(char **s, int len)
{
	char *max;
	max = s[0];
	int i;
	for(i = 1;i < len;++i)
	{
		if(strcmp(max, *(s+i)) < 0)
		{
			max = s[i];
		}
	}
	return max;
}
int main()
{
	char *s[] ={"Hello","World","China"};
	int len = sizeof (s) / sizeof (*s);

	puts(maxOfStrings(s,len));
	return 0;
}

eg 2  遍历数组

void printStrings(char **s, int len)
{
	int i;
	for(i = 0;i < len;++i)
	{
		puts(*(s + i));
	}
}

eg3  逆序数组

void swap(char **a, char **b)
{
	char *t;
	t = *a;
	*a = *b;
	*b = t;
}

void reverseStrings(char **s, int len)
{
	int i;
	for(i = 0;i < len / 2;++i)
	{
		swap(s + i, s + len - i - 1);
	}
}

 eg4  字符串选择排序

void sortStrings(char **s, int len)
{
	int i, j;
	for(i = 0;i < len - 1;++i)
	{
		for(j = i + 1;j < len;++j)
		{
			if(strcmp(s[i], s[j]) > 0)
			{
				swap(s + i, s + j);
			}
		}
	}
}

eg5    字符串二分查找

int binaryFindString(char **s, int len, const char *t)
{
	int begin = 0;
	int end = len - 1;
	int mid;
	while(begin <= end)
	{
		mid = (begin + end) / 2;
		int ret = strcmp(s[mid], t);
		if(ret < 0)
		{
			begin = mid + 1;
		}
		else if(ret > 0)
		{
			end = mid - 1;
		}
		else
		{
			return mid;
		}
	}
	return -1;
}

六、两句话技巧

1.二维数组作为函数参数,形参为指向数组的指针;

2.指针数组作为函数参数,形参为指向指针的指针。

eg1   

void foo(int (*p)[4,int rows])

int  a[3][4];

int rows = sizeof(a) / sizeof(*a);

foo(&a[0], rows);

eg  2

void bar(char **s,len)

char *s[3];

int len = sizeof(s) /sizeof(*s);

bar(&s[0], len);

你可能感兴趣的:(学习,c语言,算法,排序算法)