C言語学習のまとめ_06

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;
}

おすすめ

転載: blog.csdn.net/CZHLNN/article/details/109725147