回调函数
通过函数指针调用的函数。把函数指针作为参数传递给另一个函数,这个指针被用来调用其指向函数。
qsort函数
快速排序
整形数据
字符串数据
结构体数据
void qsort(void* base,size_t num,size_t size,int (*compar)(const void*,const void*) )
base
pointer to the first object of the array to be sorted,converted to a void*. //待排序数据中第一个对象的地址
num
待排序数据元素个数
size
排序数据中每个元素大小,单位是字节
compar
排序方法函数,比较待排序数据中2个元素的函数,返回+,交换,返回0或-,不换
//使用qsort函数排序结构体数据
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
struct stu { char *name;int age;}s[3]={ {"zhangsan",30},{"lisi,34},{"wangwu",20} };
int sort_age(const void* e1,const void* e2)
{
return ((struct stu *)e1)->age-(*(struct stu *)e2)->age;
}
int sort_name(const void* e1,const void* e2)
{
return strcmp(((struct stu*)e1->name,((struct stu*)e2)->name);
}
int main()
{
int sz = sizeof(s) / sizeof(s[0]);
//按照年龄来排序
qsort(s,sz,sizeof(s[0]),sort_age);
//按照名字来排序
qsort(s,sz,sizeof(s[0]),sort_name);
}
模仿qsort实现冒泡排序的通用算法
void swap (char *buf1,char*buf2,int width)
{
char tmp;
int i;
for(i=0;i<width;i++)
{
tmp=*buf1;
*buf1=*buf2;
*buf2=tmp;
buf1++;
buf2++;
}
}
void bubble(void* base,int sum,int width,int(*cmp)(const void *e1,const void *e2))
{
int i,j;
for(i=0;i<sum-1;i++)
{
for(j=i+1;j<sum;j++)
{
if(cmp((char*)base+i*width,(char*)base+j*width)>0)
swap((char*)base+i*width,(char*)base+j*width,width);
}
}
}
指针与数组笔试题解
sizeof(数组名)表示数组大小,&数组名表示整个数组的地址,其他情况数组名表示首元素地址
1.
#include<stdio.h>
int main()
{
int a[]={1,2,3,4};
printf("%d\n",sizeof(a));//16,sizeof(数组名)表示计算整个数组的大小
printf("%d\n",sizeof(a+0));//4或8,第一个元素的地址大小单独的数组名表示首元素地址,int*p=a
printf("%d\n",sizeof(*a));//4,第一个元素的大小
printf("%d\n",sizeof(a+1));//4或8,第二个元素的地址大小
printf("%d\n",sizeof(a[1]);//4,第二个元素的大小
printf("%d\n",sizeof(&a));//4或8,计算一个地址的大小
printf("%d\n",sizeof(*&a));//16,int(*p)[4]=&a,&a是数组指针,解引用后是数组
printf("%d\n",sizeof(&a+1));//4或8,&a+1跳过了一个数组的大小,是数组后面空间的地址
printf("%d\n",sizeof(&a[0]));//4或8
printf("%d\n",sizeof(&a[0]+1));//4或8
return 0;
}
2.
#include<stdio.h>
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
return 0;
}
3.
#include<stdio.h>
int main()
{
char arr[]={'a','b','c','d','e','f'};
printf("%d\n", strlen(arr)); //随机值,不知道'\0'在哪
printf("%d\n", strlen(arr + 0)); //随机值
printf("%d\n", strlen(*arr)); //error
printf("%d\n", strlen(arr[1])); //error
printf("%d\n", strlen(&arr)); //随机值
printf("%d\n", strlen(&arr + 1)); //随机值-6
printf("%d\n", strlen(&arr[0] + 1)); //随机值-1
return 0;
}
4.
#include<stdio.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr)); //6
printf("%d\n", strlen(arr + 0)); //6
printf("%d\n", strlen(*arr)); //error
printf("%d\n", strlen(arr[1])); //error
printf("%d\n", strlen(&arr)); //6
printf("%d\n", strlen(&arr + 1)); //随机值
printf("%d\n", strlen(&arr[0] + 1)); //5
return 0;
}
5.
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
return 0;
}
6.
int main()
{
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
printf("%d\n", sizeof(&p)); //4或8
printf("%d\n", sizeof(&p + 1)); //4或8
printf("%d\n", sizeof(&p[0] + 1)); //4或8
return 0;
}
7.
int main()
{
char *p = "abcdef";
printf("%d\n", strlen(p)); //6👻
printf("%d\n", strlen(p+1)); //5👻
printf("%d\n", strlen(*p)); //error
printf("%d\n", strlen(p[0])); //error
printf("%d\n", strlen(&p)); //随机值
printf("%d\n", strlen(&p+1)); //随机值,👻与上题的随机值无关
printf("%d\n", strlen(&p[0]+1)); //5👻
return 0;
}
8.
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]可以理解为第一行的数组名
printf("%d\n",sizeof(a[0]+1)); //👻4或8,此时a[0]作为数组名并没有放在sizeof内部,也没有取地址&,所以a[0]就是第一行第一个元素的地址,a[0]+1是第一行第二个元素的地址
printf("%d\n",sizeof(*(a[0]+1))); //👻4,*(a[0]+1)是第二个元素
printf("%d\n",sizeof(a+1)); //4或8👻此时a表示二维数组首元素的地址,即代表第一行的地址,a+1代表第二行的地址
printf("%d\n",sizeof(*(a+1))); //👻16,*(a+1)表示第二行
printf("%d\n",sizeof(&a[0]+1)); //4或8,a[0]是第一行的数组名,&a[0]+1是第二行的地址
printf("%d\n",sizeof(*(&a[0]+1))); //👻16,*(&a[0]+1)是第二行
printf("%d\n",sizeof(*a)); //👻16,*a代表第一行
printf("%d\n",sizeof(a[3])); //👻16,类型属性,sizeof通过类型计算大小
return 0;
}
表达式的属性
e.g. 3+5
值属性 - 8
类型属性 - int
#include<stdio.h>
int main()
{
short s=5;
int a=4;
printf("%d\n",sizeof(s=a+6)); //2,s=a+6没有运算,换成s++也不会运算
printf("%d\n",s); //5
}
指针笔试题
1.
//这里告知结构体的大小是20个字节
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1); //0x100014
printf("%p\n", (unsigned long)p + 0x1); //👻0x100001
printf("%p\n", (unsigned int*)p + 0x1); //👻0x100004
return 0;
}
2.
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,👻2000000,小端存储0x02 00 00 00低位放在低地址
return 0;
}
3.指针与指针相减得到之间的元素个数
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//FFFFFFFC,-4👻%p打印时内存里的补码被认为是地址,地址无正负之分,补码直接被解析为原码,按十六进制打印
return 0;
}
4.
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));
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
//👻10,5。aa+1相当于aa[1],*(aa+1)相当于aa[1][1],ptr2赋值处的(int*)可免去
return 0;
}
5.
#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++; //指向a[1],即指向at的首元素地址
printf("%s\n", *pa); //✨✨at,从*pa给的地址处开始打印字符串,**pa等于a,不能打印出at
return 0;
}
6.👍👍✨
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp); //ENTER
printf("%s\n", *--*++cpp+3); //ER
printf("%s\n", *cpp[-2]+3); //cpp[-2]相当于*(cpp-2)。**(cpp-2)+3输出ST
printf("%s\n", cpp[-1][-1]+1); //cpp[-1][-1]+1相当于*(*(cpp-1)-1)+1,输出EW
return 0;
}
7.
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) }; //👻逗号表达式,等价于int a[3][2]={1,3,5}
int *p;
p = a[0];
printf( "%d", p[0]); //1
return 0;
}