整数提升和截断

int main()
{
unsigned char a = 100;
//000000000000000000000000 0110 0100
unsigned char b = 200;
//000000000000000000000000 1100 1000
unsigned char c = 0;
c = a + b;
//000000000000000000000001 0010 1100
//c是char类型,发生截断,相当于,100+200-256

//下面的a+b没有发生截断,又是%d打印,所以整型提升过后,相加,类型是int,直接输出
printf("%d %d", a + b, c);
// 300 44
return 0;
}

杨辉三角

int main()
{
int arr[10][10] = { 0 };
int i = 0, j = 0;//i和j是下标
for (i = 0;i < 10;i++)
{
for (j = 0;j <=i;j++)
{
if (i == j)
arr[i][j] = 1;
if (j == 0)
arr[i][j] = 1;
if (i > 1 && j >0)
arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
}
}
for (i = 0;i < 10;i++)
{

for (j = 0;j <=i;j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}

二级指针的使用

text(int** pp)
{
printf("%d\n", *(*pp + 1));
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
int* p = arr;
int** pp = &p;
text(pp);
return 0;
}

函数指针

顾名思义:指向函数的指针

int add(int b,int a)
{
return a + b;
}
int main()
{
int a = 4;
int b = 3;
//text(b,a);
//int (*p)(int,int) = &add;//函数指针的定义方式,当然这里的指针p前面的*必须写
int (*p)(int, int) = add;//这里也是可以的,并且与下面的全部完全匹配
//函数名就是地址

//int ret = add(a, b);
//int ret = (*p)(a, b);
int ret = p(a, b);
//int ret = *p(a, b);//这里是错误的从右向左先计算 p(a,b)
//这里可以看出,*号在这里只是一个摆设,并没有实际意义

printf("%d\n",ret);
return 0;
}

类型转换与函数指针

typeded void(*)(int) a;//这种对于函数指针类型重定义是错误的
typedef void(*signed_t)(int);//这样才是正确的
signed_t signal(signed_t);
int main()
{
(*(void (*)())0)();
//0 ——是一个数值
//void (*)())0 ——将0的类型强制转换陈一个地址,低智商存放一个函数指针
//void(*p)()=0//相当于0变成一个地址
//*(void (*)())0 ——对于指针0进行解引用,拿出地址上面的内容
//(*(void (*)())0)() ——对内容进行使用,对于地址0上面的函数进行引用


void (*signal(int, void(*)(int)))(int);
//另一种意思相同但是无法编译通过的类型 void(*)(int) signal(int, void(*)(int)
//1、signal 是一个函数名
//2、signal函数有两个形参:一个是int,一个是函数指针
//函数指针的返回值void参数是int
//3、signal的返回类型是void参数是int

return 0;
}

对于函数指针的理解

int add(int x,int y)
{
return x + y;
}
int sub(int x, int y)
{
return x - y;
}
int mul(int x, int y)
{
return x * y;
}
int div(int x, int y)
{
return x / y;
}
int main()
{
int a = 1, b = 2, c = 3, d = 4;
int* arr[4] = { &a,&b,&c,&d };
int arr1[4] = { a,b,c,d };
int(*p1)[4] = &arr1;//p1是指向数组的一个指针,当传递过来是一个地址的时候,无论他本来是什么意思,就当作是真个数组的地址

printf("%d\n", *(arr[1]));
printf("%d\n", arr1[1]);
printf("%d\n", *(*p1+1));//因为p1是整个数组的地址,所以先取地址,得到每个元素的地址,再解引用得到内容
printf("%d\n", *(arr[1]));//arr是一个数组,先用下标取出里面的内容,是一个指针,在取内容得出一个数字
//都是2

//(指向数组的指针和指向函数的指针)的指针函数用法一致
//(存放指针的指针数组和存放函数指针的指针数组)的用法一致

int (*p[4])(int, int) = { add,sub,mul,div };
//int* (*p[4])(int,int) = { add,sub,mul,div };
//这里的星星是数组里面存储的类型,因为函数既可以是变量又可以是指针,所以加不加都为无所谓
int (*(*p2)[4])(int, int) = &p;


printf("%d\n", (*(*p2 + 0))(3, 4));
//使用数组指针的时候,必须对所取到的内容在进行一次解引用,才能得到需要的内容,并且使用
//printf("%d\n", (*(*p2)+0)(3, 4));这是错误的

printf("%d\n", p[0](3, 4));//上下相同,可以相互转换
printf("%d\n", (*(p+0))(3, 4));
return 0;
}

回调函数:对于回调函数的理解

一个函数的函数指针是另一个函数的参数

//回调函数:一个函数的函数指针是另一个函数的参数
//int text2()
//{
// int x = 1, y = 1;
// return x+y;
//}
//int text(int e1, int(*p)())//这里参数里面的函数指针必须是一个新定义的函数指针,模板必须和传递过来的函数相同
//{
// return e1 + (*p)();//这里的指针已经被定义,直接使用就可以,而且在使用的时候必须像一个真正的函数使用时一样加括号,传参数
//}
//int main()
//{
// int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
// int ret = text(arr[1], text2);
// printf("%d ", ret);
// return 0;
//}

回调函数和函数调用的区别

int text2()
{
int x = 1, y = 1;
return x + y;
}
int text(int e1)//这里参数里面的函数指针必须是一个新定义的函数指针,模板必须和传递过来的函数相同
{
int ret = text2();//这个函数名只能只想唯一的函数,而上面的可以指向不同的函数
//回调函数的真正用途是作为一种中间连接装置
//在回调函数的两头,都是由使用者制作的,即我可以使用这个中间装置,去调用任何人写的函数去实现我的功能,而不用去更改在中间装置里面的函数名
return e1 + ret;//这里的指针已经被定义,直接使用就可以,而且在使用的时候必须像一个真正的函数使用时一样加括号,传参数
}
int main()
{
int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
int ret = text(arr[1]);
printf("%d ", ret);
return 0;
}

用函数指针写一个计算器

//#define  _CRT_SECURE_NO_WARNIN  1
//int add(int x, int y)
//{
// return x + y;
//}
//int sub(int x, int y)
//{
// return x - y;
//}
//int mul(int x, int y)
//{
// return x * y;
//}
//int div(int x, int y)
//{
// return x / y;
//}
//void menu()
//{
// printf("*********************\n");
// printf("****1、add 2、sub****\n");
// printf("****3、mul 4、div****\n");
// printf("******0、exit********\n");
//
//}
//int main()
//{
// int input = 0;
// int (*p[5])(int x, int y) = {NULL, add,sub,mul,div };
// int a = 0, b = 0;
// do
// {
// menu();
// printf("请输入->");
// scanf_s("%d", &input);
// if (input>=1&&input<=4)
// {
// printf("请输入参数");
// scanf_s("%d %d", &a, &b);
// int ret = p[input](a, b);
// printf("%d\n", ret);
// }
// else if (input == 0)
// {
// break;
// }
// else
// {
// printf("输入错误\n");
// }
// } while (input);
// return 0;
//}

数组指针类型的书写

int main()
{
int arr[10] = { 0 };
//这里的int 是数组元素的类型
//这里的int [10]是数组的类型
return 0;
}