C高级学习笔记第2天

总结指针的 5个运算

  •     =  赋值运算  建立指向关系  
  •     *  取指向对象     *p 
  •     +/- n  地址移动
  •     p-q  指针相减 
  •     p>q  关系运算 

指针占用的内存大小: 

  •     指针变量指向的类型 不影响其 占用的内存大小  
  •     若 是32位机器   地址大小为 4字节 
  •     若 是64位机器   地址大小为 8字节 

指针数组 与 二级指针 

指针数组: 就是一个数组其元素是  指针 
    如图所示 : 


    ps 是一个  常量字符串指针数组 
    定义:
    存储类型  元素类型   数组名[元素个数] = {};
    auto     cosnt char * ps[6] = {"Beijing", "Moscow", "New York", "","", NULL};

    遍历指针数组:

   for(int i= 0; i<5; i++)
        printf("%s ",ps[i]);

指针方式遍历:

  • //二级指针
  • const char ** pps = ps;

    //遍历指针数组:

 for( int i = 0; i<5; i++)
        printf("%s ",*pps++);
    printf("\n");

练习: 
char *a[3] = {"hello","world","ok"};
char **p = a;

  •  假设每个表达式中p=a;求表达式代表含义或值?
  • a[0] == "hello" == char*  == %s 
  • *p   == a[0]  
  • **p  == *a[0] == 'h'
  • *a   == a[0]
  • **a  == *a[0] == 'h'
  • *p++ == a[0] 然后 p=p+1
  • *(p++) == *p++
  • **(p+1)) ==  *"world" == 'w'
  • *(*(p+1)+1)  == *(a[1]+1) == 'o'
  • (*p)++  考虑p能否进行该操作? 可以操作 
  •     先*p == a[0]  然后  a[0] = a[0]+1; a[0] ---> "ello"

数组指针 与  二维数组:

  • 二维数组:
  • int arr[2][3] = {1,2,3,4,5,6};
  • 数组指针:  含义: 一个指针 指向一个一维数组 
  • int    (*p)[3] = arr;  // p = &arr[0]; 
  • &arr[0]=0x7ffc4307c1a0   // 数组指针类型  
  •  arr   =0x7ffc4307c1a0   // 数组指针类型 
  •  arr[0]=0x7ffc4307c1a0   // 常量int类型指针 
  • &arr[0][0] =0x7ffc4307c1a0 // 常量int类型指针  
  • 问p+1是什么?  p+1  == arr[1]
  • 练习:
  • int a[2][3];
  • int (*p)[3] = a;
  • 假设每个表达式中p=a;求表达式代表含义?
  • a[0]    0号元素是一个一维数组 
  • *p      == a[0]
  • **p     == a[0][0] 
  • *a      == a[0]
  • **a     == a[0][0] 
  • *p++    == 先*p == a[0] 然后  p = p+1;  p----> a[1]
  • *(p++)  == *p++  
  • **(p+1) == *a[1] == a[1][0]
  • *(*(p+i)+j)
  •         ==  *(a[i]+j)  == a[i][j]
  •         
  • (*p)++  考虑p能否进行该操作?  不能  
  •     先*p == a[0] 然后  然后  a[0] = a[0]+1;  数组名不能赋值 

指针与函数: 

  • 指针函数:
  •         本质是一个函数, 返回值是一个指针 
  •     
  •     函数指针:
  •         本质是一个指针, 指向一个函数 
  • 代码段: 
  •     存储代码 
  •     函数名:
  •         1. 代指这个函数本身
  •         2. 代指这个函数的首地址 

函数类型: 

除去函数名 以及形参名等 名字  剩下的就是函数的类型 

函数指针定义:

指向的函数返回值类型    (*函数指针名)(函数形参类型列表) = 对应类型的函数;

函数指针应用:  回调函数 多用于写接口

接口: API  写接口时,该接口的有些内容还没有确定, 因此通过函数指针的方式 来传递参数

回调函数: 一个函数 其参数 有函数指针类型  

案例:  要求写一个函数,  参数传入一个数组, 要求输出 满足调用者条件的数?  参考funcp.c文件
void    func1(int arr,int len, 函数指针 )

#include <stdio.h>

//函数指针
int func(char a)// 函数类型 int (char)
{
	printf("hello func\n");
}

//定义一个函数指针 存放函数的地址
int (*fp)(char) = &func; 

//要求写一个函数,  参数传入一
//个数组, 要求输出 满足调用者条件的数?
//条件通过函数指针传入,  
//int condition(int num); 函数类型 
//将num 确定 否是为你需要的数 是 返回值为真
void funcf(int *arr, int len, int (*fp)(int))
{
	printf("满足条件的数有:");
	//遍历数组
	for(int i=0;i<len;i++)
	{
		if ( fp(arr[i])) printf("%d ",arr[i]);
	}
}

int arr[10] = {1,2,3,4,5,6,7,8};

//用户A的条件
int conditionA(int num)
{
	if(num % 2 == 0) return 1;
	else return 0;
}

//用户B的条件
int conditionB(int num)
{
	if(num > 5) return 1;
	else return 0;
}

int main()
{
	(&func)('A');
	printf("func=%p\n",func);
	printf("&func=%p\n",&func);
	printf("fp  =%p\n",fp);
	printf("main=%p\n",main);
	//通过函数指针 调用指向的函数
	(*fp)('B');
	fp('B');
	//调用接口
	funcf(arr, 10, conditionA);
	funcf(arr, 10, conditionB);
	return 0;
}

创建线程的函数:  了解

  • int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
  •                           void *(*start_routine) (void *), void *arg);
  •     void *(*start_routine) (void *):
  •     
  •     start_routine 是一个指针  指向一个函数  该函数类型 为 void * (void *)
  •     void * (void *) 是 一个函数类型  这个类型的函数 有一个 void*类型的返回值 
  •                         有一个 void * 的形参 

   函数指针数组:

本质是一个数组  数组中元素是 函数指针   

递归函数: 

  •     函数中 存在 自己调用自己 (递推关系) 
  •     每次自己调用自己 问题规模在逐渐减小 , 向临界条件趋近
  •     临界条件: 退出自己调用自己 的条件 
  • 示例: 递归求解 1+2+3+..+ n = ??
  •     求第n项的前n项和  S(n) = n + S(n-1);  递推式 
  •     临界条件          n == 1  S(n) == 1;

递归的特性: 

  •        本质就是 对栈区空间的 利用
  •         递推过于 深入  可能导致栈区溢出 段错误 
  •         效率不高
  •         在一些特定情况下, 使用递归可以 简化代码量 
  • 斐波那契数列
  •     1 1 2 3 5 8 13 21 34 55....
  •     A(n) = A(n-1) + A(n-2);
  •     n == 1 || n == 2  A(n) ==1;

        
作业: 
(1)杨辉三角 

1 1
1 2 1
1 3 3  1
1 4 6  4  1
1 5 10 10 5 1
.....

#include <stdio.h>

/*
int yanghui(int i,int j)
{
	return(j == 1 || j== i) ? 1: yanghui(i - 1,j - 1) + yanghui(i - 1,j);
}


int main()
{
	int n;//杨辉三角的前n行
	int i,j;
	printf("%d",yanghui(10,7));
	return 0;
}
*/

int YangHui(int r, int c)//实参i代表形参r,实参j代表形参c,即行与列
{
	return(c == 1 || c == r) ? 1 : YangHui(r - 1, c - 1) + YangHui(r - 1, c);
}
int main()
{
	int n;//杨辉三角的前n行
	int i, j;
	printf("需要输出几行杨辉三角(0~20):");
	scanf("%d", &n);
	for (i = 1; i <= n; i++)//控制每行
	{
		for (j = 0; j < n - i; j++)//每行的前n-i个位置输出空格
			printf("   ");//每次输出3个空格
		for (j = 1; j <= i; j++)//当前的第i行有j个元素,也就是:当前行是第i行,当前行一共有j列
			printf("%6d", YangHui(i, j));
		printf("\n");
	}
	return 0;
}

求 第10行 第7列的值 

(2) 递归方式 实现选择排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值