1->字符指针
//1.字符指针
int?main()
{
char?arr[]?=?"abcdef";
char*?pc?=?arr;
printf("%s\n",?arr);
printf("%s\n",?pc);
return?0;
}int?main()
{
const?char*?p?=?"abcdef";//"abcdef"是一个常量字符串
//指向元素a
//*p?=?‘w‘;
//printf("&c\n",*p);
//printf("%s\n",?p);
return?0;
}2->指针数组
//2.指针数组?
// 是数组,用来存放指针的数组
int?main()
{
int?arr[10]?=?{?0?};//整形数组
char?ch[5]?=?{?0?};//字符数组
int*?parr[4];//存放整形指针的数组?-?指针数组
char?pch[5];//存放字符指针的数组?-?指针数组
return?0;
}int?main()
{
int?arr1[]?=?{?1,2,3,4,5?};
int?arr2[]?=?{?2,3,4,5,6?};
int?arr3[]?=?{?3,4,5,6,7?};
int*?parr[]?=?{?arr1,arr2,arr3?};//存首元素地址
int?i?=?0;
for?(i?=?0;?i?<?3;?i++)
{
int?j?=?0;
for?(j?=?0;?j?<?5;?j++)
{
printf("%d?",?*(parr[i]?+?j));
}
printf("\n");
}
return?0;
}3->数组指针
//3.数组指针
// 是指针
int?main()
{
int*?p?=?NULL;?//p是整形指针?-?指向整形的指针?-?可以存放整形的地址
char*?pc?=?NULL;?//pc是字符指针?=?指向字符的指针?-?可以存放字符的地址
//数组指针?-?指向数组的指针?-?存放数组的地址
int?arr[10]?=?{?0?};
//arr?-?首元素地址
//&arr[0]?-?首元素地址
//&arr?-?数组地址
int?arr[10]?=?{?1,2,3,4,5,6,7,8,9,10?};
int(*p)[10]?=?&arr;?//方块优先级高
//上面的p就是数组指针
return?0;
}int?main()
{
int?arr[10]?=?{?1,2,3,4,5,6,7,8,9,10?};
int(*pa)[10]?=?&arr;
int?i?=?0;
for?(i?=?0;?i?<?10;?i++)
{
printf("%d?",?(*pa)[i]);?//*pa?==?arr
}
return?0;
}int?main()
{
int?arr[3][5]?=?{?{1,2,3,4,5},{2,3,4,5,6?},{3,4,5,6,7}?};
print1(arr,?3,?5);//arr?-?数组名就是首元素地址
//把arr想象成一维数组
//所以数组arr有三个元素,首元素地址就是第一行地址
print2(arr,?3,?5);
return?0;
}int?arr[5];??????????//??? int*?parr1[10];??????//parr1是一个数组,数组有10个元素,每个元素都是一个int型指针,?int*?parr1[10]是指针数组 int?(*parr2)[10]; ???//parr2是一个指针,该指针指向的了一个数组,数组有10个元素,每个元素是int型,int?(*parr2)[10]是数组指针 int?((*parr3)[10])[5];? //parr3是一个数组,该数组有10个元素,每个元素是一个数组指针,该数组指针指向的数组有五个元素,每个元素是int
4->数组参数、指针参数
//4.数组参数、指针参数
//一维数组传参
void?test(int?arr[])//ok
{}
void?test(int?arr[10])//ok
{}
void?test(int?*arr)//ok
{}
void?test2(int?*arr[20])//ok
{}
void?test2(int?**arr)//ok?
{}
int?main()
{
int?arr[10]?=?{?0?};
int?*arr2[20]?=?{?0?};
test(arr);
test2(arr2);
return?0;
}//二维数组传参
void?test(int?arr[3][5])
{}
void?test2(int?arr[][5])
{}
void?test3(int?arr[3][])?//err,不能省略列
{}
void?test4(int*?arr)?//err,传过来的是一行数组?不能用int*
{}
void?test5(int?**arr)//err,二级指针也不能接收?一个数组地址
{}
void?test6(int?(*arr)[5])
{}
int?main()
{
int?arr[3][5]?=?{?0?};
test(arr);//二维数组传参
test2(arr);
test3(arr);
test4(arr);
test5(arr);
test6(arr);
return?0;
}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素
//这样才方便运算
//二级指针传参
void?test(int**??ptr)
{
printf("num?=?%d\n",?**ptr);
}
int?main()
{
int?n?=?10;
int*?p?=?&n;
int**?pp?=?&p;
test(pp);
test(&p);
return?0;
}5->函数指针
//5.函数指针?-?是指向函数的指针?-?存放函数地址的一个指针
int?Add(int?x,?int?y)
{
int?z?=?0;
z?=?x?+?y;
return?z;
}
int?main()
{
int?a?=?10;
int?b?=?20;
int?arr[10]?=?{?0?};
int?(*p)[10]?=?&arr;
//printf("%d\n",?Add(a,?b));
//&函数名?和?函数名?都是函数的地址?
/*
printf("%p\n",?&Add);
printf("%p\n",?Add);
*/
int??(*pa)(int,?int)?=?Add;?//函数指针
printf("%d\n?",?(*pa)(2,?3));
return?0;
}
void?Print(char*str)
{
printf("%s\n",?str);
}
int?main()
{
void?(*p)(char*)?=?Print;?
(*p)("hello?bit");
return?0;
}//分析代码1 (*(void?(*)())0)(); void(*)()?-?函数指针类型 把0强制类型转换成:void(*)()?-?0就是一个函数的地址 调用0地址处的该函数 //代码2 void?(*signal(int,?void(*)(int)))(int); void(*??)(int); signal(int,?void(*)(int))? signal是一个函数声明?-?参数有两个,一个是int,第二个是函数指针,该函数指针指向的函数的参数是int,返回类型是void signal函数的返回类型也是个函数指针:?该函数指针指向的函数的参数是int,返回类型是void
int?Add(int?x,?int?y)
{
int?z?=?0;
z?=?x?+?y;
return?z;
}
int?main()
{
int?a?=?10;
int?b?=?20;
int??(*pa)(int,?int)?=?Add;?//函数指针
//以下三种都正确
printf("%d\n?",?(*pa)(2,?3));
printf("%d\n?",?pa(2,?3));
printf("%d\n?",?Add(2,?3));
return?0;
}6->函数指针数组
//6.函数指针数组?-?存放函数的地址的数组
?
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*?arr[5];
//需要一个数组,这个数组可以存放4个函数的地址?-?函数指针的数组
int?(*pa)(int,?int)?=?Add;?//Sub/Mul/Div
int?(*parr[4])(int,?int)?=?{Add,Sub,?Mul,Div};//函数指针的数组
int?i?=?0;
for?(i?=?0;?i?<?4;?i++)
{
printf("%d\n",parr[i](2,?3));
}
return?0;
}//测试题 char*?my_strcpy(char*?dest,?const?char*?src); //1.写一个函数指针?pf,能够指向my_strcpy char*?(*pf)(char*,?const?char*); //2.写一个函数指针数组pfArr,?能够存放4个my_strcpy函数的地址 char*?(*pfArr[4])(char*,?const?char*);
//函数指针案例
//计算器
void?menu()
{
printf("1.add\n2.sub\n3.Mul\n4.div\n");
}
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?Div(int?x,?int?y)
{
return?x?^?y;
}
int?main()
{
int?input?=?0;
int?x?=?0;
int?y?=?0;
do
{
menu();
printf("请选择:>");
scanf("%d",&input);
switch(input)
{
case?1:
printf("请输入两个操作数:>");
scanf("%d%d",?&x,?&y);
printf("%d\n",?Add(x,?y));
break;
case?2:
printf("请输入两个操作数:>");
scanf("%d%d",?&x,&y);
printf("%d\n",?Sub(x,?y));
break;
case?3:
printf("请输入两个操作数:>");
scanf("%d%d",?&x,?&y);
printf("%d\n",?Mul(x,?y));
break;
case?4:
printf("请输入两个操作数:>");
scanf("%d%d",?&x,?&y);
printf("%d\n",?Div(x,?y));
break;
case?0:
printf("退出\n");
break;
default:
printf("选择错误\n");
break;
}
}?while?(input);
}
//方法2.利用函数指针数组
void?menu()
{
printf("1.add\n2.sub\n3.Mul\n4.div\n5.Xor");
}
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?Xor(int?x,?int?y)
{
return?x?^?y;
}
int?main()
{
int?input?=?0;
int?x?=?0;
int?y?=?0;
//pfArr?是一个函数指针数组?-?用途:转移表
int?(*pfArr[])(int,?int)?=?{?0,Add,Sub,Mul,Div,Xor};
do
{
menu();
printf("请选择:>");
scanf_s("%d",?&input);
if?(input?>=?1?&&?input?<=?5)
{
printf("请输入操作数:>");
scanf_s("%d%d",?&x,?&y);
int?ret?=?pfArr[input](x,?y);
printf("%d\n",?ret);
}
else?if?(input?==?0)
{
printf("退出\n");
}
else
{
printf("选择错误!\n");
}
}?while?(input);
}7->指向函数指针数组的指针
//7.指向函数指针数组的指针
int?Add(int?x,?int?y)
{
return?x?+?y;
}
int?main()
{
int?arr[10]?=?{?0?};
int?(*p)[10]?=?&arr;?//取出数组的地址
int?(*pfArr[4])(int,?int);//pfArr?-?是一个数组?-函数指针的数组
//ppfArr是一个指向?函数指针数组?的指针
int(*(*ppfArr)[4])(int,?int)?=?&pfArr;?
//
//ppfArr?是一个数组指针,指针指向的数组有4个元素
//指向的数组的每个元素的类型是一个函数指针?int(*)(int,?int)
//
return?0;
}8->回调函数
//8.回调函数?-?通过函数指针调用的函数
void?print(const?char?*str)
{
printf("hehe:%s",?str);
}
void?test(void?(*p)(char*))
{
printf("test\n");
p("bit");
}
int?main()
{
test(print);
return?0;
}//void类型的指针
int?main()
{
int?a?=?10;
//int*?pa?=?&a;
//char*?pc?=?&a;
//char?ch?=?‘w‘;
void*?p?=?&a;?//无类型指针?-?可以接收任意类型的地址?-?不能进行解引用操作?-?不能进行加减整数的操作
p?=?&ch;
return?0;
}//qsort?-?库函数?-?排序?-?可以排序任意类型的数据?
//quick?sort
//void?qsort(
// void*?base,??//目标数组首元素地址
// size_t?num, ?//待排序数组元素个数
// size_t?width,?//每个元素的大小-单位是字节
// int?(*cmp)(const?void*?e1,?const?void*?e2)?//函数指针,比较两个元素的所用函数的地址?-?这个函数使用者自己实现?-?函数指针的两个参数是:待比较的两个元素的地址
//);
//对arr进行排序,排成升序
//冒泡排序函数只能排序整形数组
//bubble_sort(arr,?sz);//冒泡排序函数?
//void?bubble_sort(int?arr[],?int?sz)
{
//确定冒泡排序的趟数
int?i?=?0;
for?(i?=?0;?i?<?sz?-?1;?i++)
{
int?flag?=?1;//假设这一趟要排序的数据已经有序?
//每一趟冒泡排序
int?j?=?0;
for?(j?=?0;?j?<?sz?-?1?-?i;?j++)
{
if?(arr[j]?>?arr[j?+?1])
{
int?tmp?=?arr[j];
arr[j]?=?arr[j?+?1];
arr[j?+?1]?=?tmp;
flag?=?0;
}
}
if?(flag?==?1)
{
break;
}
}
}
struct?stu
{
char?name[20];
int?age;
};
int?cmp_int(const?void*?e1,?const?void*?e2)?//void*?-?可以接收任意类型的地址
{
//比较两个整形值的
return?*(int*)e1?-?*(int*)e2;
}
int?cmp_float(const?void*?e1,?const?void*?e2)
{
//比较两个浮点型
return?((int)(*(float*)e1?-?*(float*)e2));
}
int?cmp_stu_by_age(const?void*?e1,?const?void*?e2)
{
//比较两个年龄
return?((struct?stu*)e1)->age?-?((struct?stu*)e2)->age;
}
int?cmp_stu_by_name(const?void*?e1,?const?void*?e2)
{
//比较名字就是比较字符串
//字符串比较不能直接用><=来比较,应该用strcmp函数
return?strcmp(((struct?Stu*)e1)->name?,((struct?Stu*)e2)->name);
}
void?test1()
{
int?arr[10]?=?{?9,8,7,6,5,4,3,2,1,0?};
int?sz?=?sizeof(arr)?/?sizeof(arr[0]);
qsort(arr,?sz,?sizeof(arr[0]),?cmp_int);
int?i?=?0;
for?(i?=?0;?i?<?sz;?i++)
{
printf("%d?",?arr[i]);
}
}
void?test2()
{
float?f[]?=?{?9.0,?8.0,?7.0,?6.0,?5.0,?4.0?};
int?sz?=?sizeof(f)?/?sizeof(f[0]);
qsort(f,?sz,?sizeof(f[0]),?cmp_float);
int?i?=?0;
for?(i?=?0;?i?<?sz;?i++)
{
printf("%f?",?f[i]);
}
}
void?test3()
{
struct?stu?s[3]?=?{?{"zhangsan",20},{"lisi",30},{"wangwu",10}?};
int?sz?=?sizeof(s)?/?sizeof(s[0]);
qsort(s,?sz,?sizeof(s[0]),?cmp_stu_by_age);
int?i?=?0;
for?(i?=?0;?i?<?sz;?i++)
{
printf("%d?",?s[i]);
}
}
void?test4()
{
struct?stu?s[3]?=?{?{"zhangsan",20},{"lisi",30},{"wangwu",10}?};
int?sz?=?sizeof(s)?/?sizeof(s[0]);
qsort(s,?sz,?sizeof(s[0]),?cmp_stu_by_name);
int?i?=?0;
for?(i?=?0;?i?<?sz;?i++)
{
printf("%s?",?s[i]);
}
}
//实现bubble_sort函数的程序员,他是否知道未来排序的数据类型-不知道
//那程序员也不知道,待比较的两个元素的类型
void?Swap(char*?buf1,?char*?buf2,?int?width)
{
int?i?=?0;
for?(i?=?0;?i?<?width;?i++)
{
char?tmp?=?*buf1;
*buf1?=?*buf2;
*buf2?=?tmp;
buf1++;
buf2++;
}
}
void??bubble_sort(void*?base,?int?sz,?int?width,?int?(*cmp)(const?void*?e1,?const?void*?e2))
{
int?i?=?0;
for?(i?=?0;?i?<?sz?-?1;?i++)
{
//每一趟冒泡排序
int?j?=?0;
for?(j?=?0;?j?<?sz?-?1?-?i;?j++)
{
//两个元素的比较
if?(cmp((char*)base+j*width,(char*)base+(j+1)*width)?>?0)
{
//交换
Swap((char*)base?+?j?*?width,?(char*)base?+?(j?+?1)?*?width,?width);
}
}
}
}
int?cmp_stu_by_age(const?void*?e1,?const?void*?e2)
{
//比较两个年龄
return?((struct?stu*)e1)->age?-?((struct?stu*)e2)->age;
}
void?test5()
{
struct?stu?s[3]?=?{?{"zhangsan",20},{"lisi",30},{"wangwu",10}?};
int?sz?=?sizeof(s)?/?sizeof(s[0]);
//使用bubble_sort的程序员一定知道自己排序的是什么数据
//就应该知道如何比较待排序数组中的元素
bubble_sort(s,?sz,?sizeof(s[0]),cmp_stu_by_age);
}
int?main()
{
??
//通过qsort排序
test1();?//排序整型数组
test2();?//排序浮点型数组
test3();?//排序-?通过结构体数组的年龄
test4();?//排序-?通过结构体数组的名字
test5();?//仿照qsort来修改冒泡函数实现能够排序任意类型
return?0;
}9->指针和数组面试题的解析
//9.指针和数组面试题的解析
int?main()
{
//数组名是首元素地址
//例外
//1.sizeof(数组名)?-?数组名表示整个数组
//2.&数组名?-?数组名表示整个数组
??//
//一维数组
int?a[]?=?{?1,2,3,4?};
printf("%d\n",?sizeof(a));????//sizeof(数组名)?-?计算的是数组总大小?-?单位是字节?-16
printf("%d\n",?sizeof(a?+?0));//?4/8?-?数组名这里表示首元素的值,a+0还是首元素地址,地址的大小就是4/8个字节
printf("%d\n",?sizeof(*a));???//4?-?数组名表示首元素地址,*a就是首元素
printf("%d\n",?sizeof(a?+?1));//?4/8?-?第二个元素的地址,地址的大小就是4/8个字节
printf("%d\n",?sizeof(a[1]));?//4?-?第2个元素的大小
printf("%d\n",?sizeof(&a));???//?4/8?-?&a取出的是数组的地址,但是数组地址那也是地址,地址的大小就是4/8个字节
printf("%d\n",?sizeof(*&a));??//16
printf("%d\n",?sizeof(&a?+?1));?//?4/8
printf("%d\n",?sizeof(&a[0])); //?4/8
printf("%d\n",?sizeof(&a[0]?+?1));//?4/8
return?0;
}//字符数组
int?main()
{
char?arr[]?=?{?‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘?};
printf("%d\n",?sizeof(arr));; //6
printf("%d\n",?sizeof(arr?+?0));//?4/8
printf("%d\n",?sizeof(*arr));???//?1
printf("%d\n",?sizeof(arr[1]));?//1
printf("%d\n",?sizeof(&arr)); //4/8
printf("%d\n",?sizeof(&arr?+?1));?//?4/8
printf("%d\n",?sizeof(&arr[0]?+?1));?//?4/8
printf("%d\n",?strlen(arr)); //?随机值
printf("%d\n",?strlen(arr?+?0));//?随机值
//printf("%d\n",?strlen(*arr));???//?err
//printf("%d\n",?strlen(arr[1]));?//?err
printf("%d\n",?strlen(&arr)); //?随机值
printf("%d\n",?strlen(&arr?+?1));?//随机值-6
printf("%d\n",?strlen(&arr[0]?+?1));?//随机值-1
return?0;
}
int?main()
{
char?arr[]?=?"abcdef";
printf("%d\n",?sizeof(arr)); //?7??
printf("%d\n",?sizeof(arr?+?0));//?4/8
printf("%d\n",?sizeof(*arr)); //1
printf("%d\n",?sizeof(arr[1]));?//1
printf("%d\n",?sizeof(&arr));???//?4/8
printf("%d\n",?sizeof(&arr?+?1));//?4/8
printf("%d\n",?sizeof(&arr[0]?+?1));//?4/8
printf("%d\n",?strlen(arr)); //?6
printf("%d\n",?strlen(arr?+?0));//?6
//printf("%d\n",?strlen(*arr)); //err
//printf("%d\n",?strlen(arr[1]));?//err
printf("%d\n",?strlen(&arr));???//?6
printf("%d\n",?strlen(&arr?+?1));//随机值
printf("%d\n",?strlen(&arr[0]?+?1));//?5
return?0;
}
int?main()
{
const?char*?p?=?"abcdef";
printf("%d\n",?sizeof(p)); //?4/8
printf("%d\n",?sizeof(p?+?1)); //?4/8
printf("%d\n",?sizeof(*p)); //?1
printf("%d\n",?sizeof(p[0])); //?1 p[0]?==?*(p?+?0)?==?‘a‘
printf("%d\n",?sizeof(&p)); //?4/8
printf("%d\n",?sizeof(&p?+?1)); //?4/8
printf("%d\n",?sizeof(&p[0]?+?1));//?4/8
printf("%d\n",?strlen(p)); //?6
printf("%d\n",?strlen(p?+?1)); //?5
//printf("%d\n",?strlen(*p)); //?err
//printf("%d\n",?strlen(p[0])); //?err p[0]?==?*(p?+?0)?==?‘a‘
printf("%d\n",?strlen(&p)); //?随机值
printf("%d\n",?strlen(&p?+?1)); //?随机值
printf("%d\n",?strlen(&p[0]?+?1));//?5
return?0;
}//二维数组
int?main()
{
int?a[3][4]?=?{?0?};
printf("%d\n",?sizeof(a));?//?48
printf("%d\n",?sizeof(a[0][0]));//4
printf("%d\n",?sizeof(a[0]));???//16??a[0]相当于第一行做为一维数组的数组名?==?sizeof(数组名)
? printf("%d\n",?sizeof(a[0]?+?1));//?4/8?a[0]是第一行首元素地址?a[0]+1,第一行第二个元素的地址
printf("%d\n",?sizeof(*(a[0]?+?1)));//4
printf("%d\n",?sizeof(a?+?1));???//4/8??a是二维数组的首元素地址,而二维数组的首元素是第一行,及把二位数组看作了一维数组,a+1就是第二行的地址
printf("%d\n",?sizeof(*(a?+?1)));//16
printf("%d\n",?sizeof(&a[0]?+?1));//4/8?第二行地址
printf("%d\n",?sizeof(*(&a[0]?+?1)));//16
printf("%d\n",?sizeof(*a));?//16?*a?=?第一行地址解引用
printf("%d\n",?sizeof(a[3]));?//16?表示第四行,sizeof不参与真实计算
return?0;
}//指针笔试题
int?main()
{
int?a[5]?=?{?1,2,3,4,5?};
int*?ptr?=?(int*)(&a?+?1);?//&a?+?1?为5后面的地址
printf("%d,?%d\n",?*(a?+?1),?*(ptr?-?1));?//2?5??
return?0;
}
struct?Test
{
int?Num;
char*?pcName;
short?sDate;
char?cha[2];
short?sBa[4];
}*p;?//结构体指针?p
//假设p?的值为ox100000,如下表表达式的值分别为多少?
//已知,?结构体Test类型的变量大小是20个字节
int?main()
{
p?=?(struct?Test*)0x100000;
printf("%p\n",?p?+?0x1);??//0x00100014?
printf("%p\n",?(unsigned?long)p?+?0x1);?//0x00100001
printf("%p\n",?(unsigned?int*)p?+?0x1);?//0x00100004
return?0;
}
?
int?main()
{
int?a[4]?=?{?1,2,3,4?};
int*?ptr1?=?(int*)(&a?+?1);
int*?ptr2?=?(int*)((int)a?+?1);
printf("%x,%x",?ptr1[-1],?*ptr2);//?4?0x02000000
return?0;
}
int?main()
{
int?a[3][2]?=?{?(0,1),(2,3),(4,5)?};//逗号表达式?1,3,5
int*?p;
p?=?a[0];?//第一行?1,?3
printf("%d",?p[0]);?//1?
return?0;
}
int?main()
{
int?a[5][5];
int(*p)[4];
p?=?a;//int?(*)[4]?----?int?(*)[5]
printf("%p,%d\n",?&p[4][2]?-?&a[4][2],?&p[4][2]?-?&a[4][2]);//0xfffffffc?,?4
return?0;
}
int?main()
{
int?aa[2][5]?=?{?1,2,3,4,5,6,7,8,9,10?};
int*?ptr1?=?(int*)(&aa?+?1);
int*?ptr2?=?(int*)(*(aa?+?1));?//*(aa?+?1)?==?aa[1]
printf("%d,%d\n",?*(ptr1?-?1),?*(ptr2?-?1));?//?10?5
return?0;
}
int?main()
{
char*?a[]?=?{?"work","at","alinbaba"?};
char**?pa?=?a;
pa++;
printf("%s\n",?*pa);//at
return?0;
}原文:https://blog.51cto.com/u_15157811/2833720