嵌入式学习第十三天!(const指针、函数指针和指针函数、构造数据类型)

1. const指针

    const关键字,常量(只读)

const int *p;
int const *p;
int *const p;
const int *const p;
int const *const p;

    1和2是等价的:const修饰p,指针变量p的值可以改变, 但不能利用指针修改指向空间中的值

    3:const修饰p,指针变量p的值不能改变,但可以利用指针变量p修改指向空间中的值(一定要对指针初始化)

    4和5是等价的:const修饰p和*p,指针变量p的值不能改变,也不能利用*p改变直系那个空间中的值(一定要初始化)

2. void

//高精度
int *p;
double *p;
char *p;
//低精度
void *p  //p保存内存地址

    int * 、double * 、char * 转换为void * 需要强制类型转换

    void *转换为int * 、double * 、char * 不需要强制类型转换

    strcpy拷贝字符串

    memcpy拷贝一段内存空间

3. 函数指针和指针函数

    指针函数:是函数,函数的返回值类型是指针类型

    函数指针:是指针,指针指向了函数

    1. 指针函数:

        局部变量的地址不能返回,因为局部变量会随函数作用域结束被回收,虽然能获得返回的地址,但地址对应的空间已经被回收过了

        将函数的返回值作为下一个函数的参数

    2. 函数指针:

int (*Fun)(int a, int b) = NULL;

        定义函数指针变量Fun,占8个字节空间,指向int返回值2个int参数的函数

    练习:

        1. 定义一个指针函数,实现字符串数组用来拷贝的strcpy函数

#include char *Mystrcpy(char *pdst, char *psrc)
{
	char *pret = pdst;
	while(*psrc != '\0')
	{
		*pdst = *psrc;
		psrc++;
		pdst++;
	}
	*pdst = '\0';
	
	return pret;
}
int main(void)
{
	char str[32] = {0};
	char dst[32] = {0};
	
	Mystrcpy(dst, Mystrcpy(str, "hello world"));
	printf("str = %s\n",str);
	printf("dst = %s\n",dst);
}

        2. 利用函数指针,实现数组的排序(升序、降序、绝对值升序、绝对值降序)

#include #include int InputArray(int *parray, int len)
{
	int i = 0;
	for(i = 0; i < len; i++)
	{
		scanf("%d",&parray[i]);
	}
	return 0;
}
int SortArray(int *parray, int len, int (*pcompay)(int, int))
{
	int i = 0;
	int j = 0;
	int tmp = 0;
	for(j = 0; j < len-1; j++)
	{
		for(i = 0; i < len-1-j; i++)
		{
			if(pcompay(parray[i], parray[i+1]))
			{
				tmp = parray[i];
				parray[i] = parray[i+1];
				parray[i+1] = tmp;
			}
		}
	}
	
	return 0;
}
int OutputArray(int *parray, int len)
{
	int i = 0;
	for(i = 0; i < len; i++)
	{
		printf("%d ",parray[i]);
	}
	printf("\n");
	return 0;
}
int AscCompare(int num1, int num2)
{
	if(num1 > num2)
	{
		return 1;
	}
	return 0;
}
int DescCompare(int num1, int num2)
{
	if(num1 < num2)
	{
		return 1;
	}
	return 0;
}
int AbsAscCompare(int num1, int num2)
{
	if(abs(num1) > abs(num2))
	{
		return 1;
	}
	return 0;
}
int AbsDeascCompare(int num1, int num2)
{
	if(abs(num1) < abs(num2))
	{
		return 1;
	}
	return 0;
}
int main(void)
{
	int a[5] = {0};
	InputArray(a, 5);
	SortArray(a, 5, AscCompare);
	printf("升序: ");
	OutputArray(a, 5);
	SortArray(a, 5, DescCompare);
	printf("降序: ");
	OutputArray(a, 5);
	SortArray(a, 5, AbsAscCompare);
	printf("绝对值升序: ");
	OutputArray(a, 5);
	SortArray(a, 5, AbsDeascCompare);
	printf("绝对值降序: ");
	OutputArray(a, 5);
	return 0;
}

4. C语言中二级指针使用场景:

    1. 指针数组传参时:

char *str[5];
int Fun(char **ppstr, int len);

    2. 函数体内想修改函数体外指针变量值的时候,要传递指针变量的地址即二级指针

char *p = NULL;
int Fun(char **pp);

5. 构造数据类型:

    数据类型:

        1. 基本数据类型:

            int、double、 char

        2. 构造数据类型:
            1. struct 结构体
            2.union 共用体
            3. enum 枚举

    1. 结构体:

        1. 结构体类型的定义
struct 结构体名
{
    数据类型1 成员变量1;
    数据类型2 成员变量2;
    数据类型3 成员变量3;
    ......
};
        2. 结构体变量的定义
数据类型 变量名;
数据类型 *指针变量名;
        3. 结构体变量的初始化
            1. 全部初始化:
struct students = {"zhangsan", 'm', 19, 100};
            2. 局部初始化:
struct student stu = {
    .name = "lisi",
    .score = 90,
};
        4. 结构体成员变量的访问:

            . :结构体变量类型访问成员变量使用 .

            ->:结构体指针类型访问成员变量使用 ->

            整体类型由成员变量类型决定

作业:

        1. 定义一个结构体包含年-月-日三个成员,从终端接收年月日信息存放到结构体中,计算该年为第几天?计算该年剩余多少天?打印年月日信息

#include #include struct data
{
	int year;
	int mon;
	int day;
};
int IsLeepYear(int Year)
{
	if(Year % 400 == 0)
	{
		return 1;
	}
	else if(Year % 4 ==0 && Year % 100 != 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
int GetDayOfYear(int Year, int Mon, int Day)
{
	int i = 0;
	int NowDay = 0;
	for(i = 0; i < Mon; i++)
	{
		if(i==1 || i==3 || i==5 || i==7 || i==8 || i==10 || i==12)
		{
			NowDay += 31;
		}
		else if(i == 4 || i ==6 || i == 9 || i==11)
		{
			NowDay += 30;
		}
		else if(i == 2)
		{
			if(IsLeepYear(Year))
			{
				NowDay += 29;
			}
			else
			{
				NowDay += 28;
			}
		}
	}
	NowDay += Day;
	return NowDay;
}
int GetLeftDayOfYear(int Year,int Mon,int Day)
{
	int RemDay = 0;
	if(IsLeepYear(Year))
	{
		RemDay = 366 - GetDayOfYear(Year, Mon, Day);
	}
	else
	{
		RemDay = 365 - GetDayOfYear(Year, Mon, Day);
	}
	return RemDay;
}
int main(void)
{
	struct data d;
	int NowDay = 0;
	int RemDay = 0;
	memset(&d, 0, sizeof(d));
	scanf("%d%d%d", &d.year, &d.mon, &d.day);
	
	NowDay = GetDayOfYear(d.year, d.mon, d.day);
	RemDay = GetLeftDayOfYear(d.year, d.mon, d.day);
	printf("%d-%d-%d是此年的第%d天,还剩余%d天\n", d.year, d.mon, d.day,
			NowDay, RemDay);
	return 0;
}

        2. 封装一个函数,给定一个数字字符串转换成其对应的整型数

                如:“123456”   得到123456

#include #include int MyAtoi(char *pstr)
{
	int sum = 0;
	while(*pstr != '\0')
	{
		sum *= 10;
		sum += (*pstr-'0');
		pstr++;
	}
	return sum;
}
int main(void)
{
	char num[32] = {0};	
	int sum = 0;
	gets(num);
	sum = MyAtoi(num);
	printf("%d\n",sum);
	return 0;
}