1.コールバック関数の使用と理解
#include<stdio.h>
#include<windows.h>
#include<assert.h>
//模拟实现qsort(用冒泡排序的思想)
//涉及回调函数:
//回调函数就是通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数
//当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。一般回调函数需要程序员
//自己实现。比如qsort就是典型的回调函数的应用
/*
arr:待排序序列
num:待排序序列中的元素个数
size:待排序序列中的元素类型的大小
comp:函数指针--->要自定义的比较函数
int(*comp)(const void*, const void*):
形参的意义:待排序数据序列任意两个元素的地址
*/
int CompInt(const void* x_, const void* y_)
{
int *n1 = (int*)(x_);
int *n2 = (int*)(y_);
//升序
if (*n1 > *n2){
return 1;
}
else if (*n1 < *n2){
return -1;
}
else{
return 0;
}
}
int CompStr(const void* x_, const void* y_)
{
char *s1 = *(char**)(x_);
char *s2 = *(char**)(y_);
return strcmp(s1, s2);
}
void swap(char* src, char* dst, int size)
{
while (size)
{
char temp = *src;
*src = *dst;
*dst = temp;
size--;
src++;
dst++;
}
}
void my_qsort(void *arr, int num, int size, int(*comp)(const void*, const void*))
{
assert(arr && comp);
char *e = (char*)arr;//想让以一个字节为单位进行操作,也就是说这里面我只用到了
//char是一个字节大小的特征,至于它的类型我们不关心。
for (int i = 0; i < num - 1; i++){
int flag = 1;
for (int j = 0; j < num - 1 - i; j++){
if (comp(e+j*size,e+(j+1)*size)>0){
//执行交换逻辑
flag = 0;
swap(e+j*size,e+(j+1)*size,size);
}
}
if (flag){
break;
}
}
}
//打印指针数组
void PrintStr(char** str, int size)
{
for (int i = 0; i < size; i++)
{
printf("str[%d]=%s\n", i,*(str + i));
}
}
void PrintInt(int arr[], int size)
{
for (int i = 0; i < size; i++)
{
printf("arr[%d]=%d\n", i, arr[i]);
}
}
int main()
{
//指针数组
//char* str[] = { "aaa", "ddd", "ccc", "bbb" };
int arr[] = {
99, 11, 22, 66, 55, 44 };
//int num = sizeof(str) / sizeof(str[0]);
int num1 = sizeof(arr) / sizeof(arr[0]);
int size = sizeof(char*);
printf("排序前:\n");
//PrintStr(arr, num1);
PrintInt(arr, num1);
my_qsort(arr, num1, size,CompInt);
printf("排序后:\n");
PrintInt(arr, num1);
//PrintStr(arr, num1);
system("pause");
return 0;
}
2.ポインタと配列の関係:
#include<stdio.h>
#include<windows.h>
int main()
{
一维数组
//int a[] = { 1, 2, 3, 4 };
数组大小:16个字节
//printf("%d\n", sizeof(a));
int* 大小为4字节,64位平台下:8字节
//printf("%d\n", sizeof(a+0));
对数组名解引用,就是数组的第一个元素:int类型大小:4字节
//printf("%d\n", sizeof(*a));
&a[1]===>为地址,类型为int*,大小:4个字节
//printf("%d\n", sizeof(a+1));
4个字节
//printf("%d\n", sizeof(a[1]));
对数组名取地址,代表整个数组的地址,
和数组首元素的地址在数值上相同,但是类型不同
//printf("%d\n", sizeof(&a));
sizeof(arr)===>代表整个数组的大小:16个字节
//printf("%d\n", sizeof(*&a));
数组指针,只要是指针类型,大小均为4或者8字节
//printf("%d\n", sizeof(&a+1));//4
//printf("%d\n", sizeof(&a[0]));//4
//printf("%d\n", sizeof(&a[0]+1));//4
//printf("*************************************************************\n");
//printf("字符数组:\n");
字符数组
//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("********************************\n");
//printf("%d\n", strlen(arr));//>=6
//printf("%d\n", strlen(arr+0));//>=6
printf("%d\n", strlen(*arr));//报错:实参和形参的类型不匹配strlen(const char* str)报错
printf("%d\n", strlen(arr[1]));//同上
//printf("%d\n", strlen(&arr));//数组指针
//printf("%d\n", strlen(&arr+1));//数组指针+1
//printf("%d\n", strlen(&arr[0]+1));//>=5
//
//printf("*********************************\n");
//char arr1[] = "abcdef";
//printf("%d\n", sizeof(arr1));//7个字节,因为还有'\0'
//printf("%d\n", sizeof(arr1+0));//arr+0为指向字符a的指针,大小为4/8
//printf("%d\n", sizeof(*arr1));//1
//printf("%d\n", sizeof(arr1[1]));//1
//printf("%d\n", sizeof(&arr1));//4/8
//printf("%d\n", sizeof(&arr1+1));//4/8
//printf("%d\n", sizeof(&arr1[0]+1));//4/8
//printf("****************************");
//printf("%d\n", strlen(arr1));
//printf("%d\n", strlen(arr1+0));
//printf("%d\n", strlen(*arr1));
//printf("%d\n", strlen(arr1[1]));
//printf("%d\n", strlen(&arr1));
//printf("%d\n", strlen(&arr1+1));
//printf("%d\n", strlen(&arr1[0]+1));
//
//char *p = "abcdef";
//printf("%d\n", sizeof(p));
//printf("%d\n", sizeof(p+1));
//printf("%d\n", sizeof(*p));
//printf("%d\n", sizeof(p[0]));
//printf("%d\n", sizeof(&p));
//printf("%d\n", sizeof(&p+1));
//printf("%d\n", sizeof(&p[0]+1));
//printf("%d\n", strlen(p));
//printf("%d\n", strlen(p+1));
//printf("%d\n", strlen(*p));
//printf("%d\n", strlen(p[0]));
//printf("%d\n", strlen(&p));
//printf("%d\n", strlen(&p+1));
//printf("%d\n", strlen(&p[0]+1));
//二维数组
int arr2[3][4] = {
0 };
//二维数组可以看成是一维数组,数组中的元素为一维数组
//arr2[0]可以看作一维数组名
printf("%d\n", sizeof(arr2) );//48
printf("%d\n", sizeof(arr2[0][0]) );//4
printf("%d\n", sizeof(arr2[0]) );//16
printf("%d\n", sizeof(arr2[0]+1) );//4,第二个一维数组的第二个元素的地址
printf("%d\n", sizeof(*(arr2[0]+1)) );//4,第二个一维数组
printf("%d\n", sizeof(arr2+1));//4,第二个元素-->第二个一维数组的地址
printf("%d\n", sizeof(*(arr2+1)) );//16,第二个一维数组
printf("%d\n", sizeof(&arr2[0]+1) );//4,第二个一维数组的地址
printf("%d\n", sizeof(*(&arr2[0] + 1)) );//16
printf("%d\n", sizeof(*arr2));//16,第一个一维数组
printf("%d\n", sizeof(arr2[3]));//16
/*
总结:
只有sizeof(数组名)
&数组名
这两种情况数组名表示整个数组,除此之外所有的数组名都代表
首元素的地址,这个首元素是广义的首元素,比如二维数组的首元素。
*/
system("pause");
return 0;
}