指针的基础和进阶

/*一.指针
//1.
一个比特位可以存储一个二进制位的0或1
1byte(比特位) = 8bit(字节)
1kb = 1024bit;
1mb = 1024kb;
1gb = 1024mb;
1tb = 1024gb;
1pb = 1024tb;
内存单元编号=地址=指针
int 类型有32个二进制位(0/1)


/
//2.
#include<stdio.h>
int main()
{
    int a = 10;
    printf("%p\n", &a);//&取地址操作符  取较小的地址  %p以十六进制打印地址
    int* pa = &a;//pa  是指针变量-存放地址-地址有时被称为指针,指针变量是用来存放指针的,而指针是指地址;
    printf("%p\n", pa);
    *pa=20;//这里的*是解引用操作符 *pa=a=20;
    printf("%d\n", a);

    char c = 'c';
    char* ch = &c;

    return 0;
}

/
//3.
//指针变量的大小
//1.指针变量是专门用来存放地址的,指针变量的大小取决于地址存放所需要的大小
//2.32位机器上:地址线是32根,地址的二进制序列就是32bit位,需要4个字节的空间,所以要4个字节的大小
//3.64位机器是8个字节
#include<stdio.h>
int main()
{
    printf("%d\n", sizeof(char*));//都是4个字节
    printf("%d\n", sizeof(int *)); 
    printf("%d\n", sizeof(double*));
    printf("%d\n", sizeof(short*));
    return 0;
}
/

//4.
//指针类型的意义
//内存窗口中存储的是地址    值     值的解析(有一定的参考价值)
#include<stdio.h>
int main()
{
    int a = 0x11112233;
    char* pa =(char*) &a;
    int* pb = &a;
    *pa = 0;//0x00112233区别只能访问一个字节
    *pb = 0;//0x00000000访问4个字节
    //double* 8个字节
    //short* 2个字节

    //加减整数
    int a = 10;
    int* pa = &a;
    char* pc = (char*)&a;
    printf("%p\n", pa);
    printf("%p\n", pc);
    printf("pa+1=%p\n", pa + 1);//跳过四个字节
    printf("pc+1=%p\n", pc + 1);//跳过一个字节
    //指针类型加减整数所走的距离
    //用指针和数组结合
    int arr[10] = {0};
    int* p = &arr[0];//四个字节改一次
    //char* p1 =(char*) &arr[0];//每一个字节改一次
    for (int i = 0; i < 10; i++)
    {
        //arr[i]=i;
        *p=i;
         p++;
    }
    p = &arr[0];
    for (int i = 0; i, 10; i++)
    {
        printf("%d", *p);
        p++;
    }
    return 0;
}
/

5.
//void*的使用
#include<stdio.h>
int main()
{
    int a = 10;
    char ch = 'w';
    void* pv = &a;
    void* pv2 = &ch;//void*的指针可以接收任何类型的地址,但是不能进行解引用操作不知道跳过几个字节

    return 0;
}

/
//6.const修饰变量(常属性)
#include<stdio.h>
int main()
{
    const int a = 10;
    //a = 20;//a无法修改但还是变量,const仅仅是在语法上进行了限制   本质上叫做常变量

    //const int* pa = &a;//const可以用来修饰指针
    //*pa = 0;不合理的操作
    printf("%d", a);

    //const修饰指针时可以放在*之前,也可以放在*之后
    //const int* p = int const* p;修饰限制*p,无法通过p来修改p指向的空间的内容
    //int* const p=&a;==int *p=&a;const修饰的是p;
    //p里面存放的是(a的地址)
    //p是变量,有自己的地址
    //*p是p指向的空间
    //const放在*左边,限制的是*p,p无法指向其他的指针,无法通过p来修改p指向的空间的内容
    //const放在*右边,限制的是p,p无法修改  *p可以修改
    //两个地方都加上const,就都不能进行修改
    return 0;
}

/
//7.
//指针的运算
//1.指针加减整数
#include<stdio.h>
int main()
{
    int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
    int* p = &arr[0];
    for (int i = 0; i < 10; i++)
    {
        printf("%d" ,* p);//printf("%d",*(p+i));
        p++;//p改变
        //p+=i;p不变
    }
    return 0;
}

//2.指针加减指针
#include<stdio.h>
int main()
{
    //指针-指针==地址-地址
    int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
    printf("%d\n", &arr[9] - &arr[0]);//9 指针减指针的绝对值得到的是元素之间的个数
    //指针减指针的前提条件是:两个指针指向同一块空间
    return 0;
}
//指针加减指针用处
#include<stdio.h>
#include<string.h>
int my_strlen(const char* s)//(char* s)
{
    int count = 0;
    while (*s != '\0')//==(*s)
    {
        count++;
        s++;
    }
    return count;
    //const char* strat = s;
    //while (*s != '\0')
    //{
    //    s++;
    //}
    //return s - strat;
}
int main()
{
    int len = strlen("abc");//a b c \0
    int len1 = my_strlen("abcdef");
    printf("%d\n", len);//strlen统计的是\0之前的字符的个数
    printf("%d\n", len1);
    return 0;
}
//3.
#include<stdio.h>
int main()
{
    int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    int* p = &arr[0];
    while (p < arr + sz)//arr数组名其实就是数组首元素地址
    {
        printf("%d", *p);
        p++;
    }
    return 0;
}

/
//8.野指针
//一个指针指向一块空间(没有明确的限制,随机的,不正确的)
//1.未初始化
//#include<stdio.h>
//int main()
//{
//    int* ptr;//
//  *ptr=200;//非法访问内存
//    printf("%p\n", ptr);
//    return 0;
//}
//局部变量不初始化为随机值
//全局,静态变量不初始化默认为0(都放在静态区)
//2.越界访问
//#include<stdio.h>
//int main()
//{
//    int arr[5] = { 0 };
//    int* p = &arr[0];
//    for (int i = 0; i < 10; i++)
//    {
//        *p = i;
//        p++;
//    }
//    return 0;
//}
//3.指针指向的空间被释放
#include<stdio.h>
int* test()
{
    int a = 10;
    return &a;
}
int main()
{
    int* p = test();
    int* p=NULL;无法使用改地址,读写该地址会报错
    printf("hehe\n");
    printf("%d\n", *p);
    return 0;
}
//不用指针时及时将指针置空


/
//9.
//assert断言(要用头文件assert.h)
//会自动标出错误行号
#include<stdio.h>
#include<assert.h>//在release版本中会自动省略assert
int main()
{
    int a = 10;
    int* p = &a;
    //p = NULL;
    assert(p);//会报具体错误
   //assert可以用来判断其他的值
    //int b = 10;
    //assert(b == 5);
    return 0;
}
//#define NDEBUG放在assert之前可以无需更改即可关闭断言


/
//10.指针的使用和传值调用,传址调用
#include<stdio.h>
#include<string.h>
#include<assert.h>
//int add(int a, int b)
//{
//    return a + b;
//}
size_t my_strlen(const char* s)
{
    size_t count = 0;
    assert(*s != NULL);
    while (*s!='\0')
    {        
        count++;
        s++;
    }
    return count;
}
int main()
{
    //int a = 10;
    //int b = 20;
    //int ret = add(a, b);//传值调用
    //printf("%d", ret);
    //return 0;


    //strlen的代码实现
    char arr[] = "abcdef";
    //size_t len = strlen(arr);//(size_t==unsigned int)
    size_t len = my_strlen(arr);//首元素地址  传址调用
    printf("%zd\n", len);//打印size_t用%zd
    return 0;
}


#include<stdio.h>
//void swap(int x, int y)//形参
//{
//    printf("%p", &x);//010FFC54
//    printf("%p", &y);//010FFC58
//}
void swap1(int* x, int* y)
{
    //x和y有自己的地址
    //printf("%p", &x);//004FFB6C
    //printf("%p", &y);//004FFB70
    //printf("%p\n", x);//00BAF7DC
    //printf("%p\n", y);//00BAF7D0
    //*x=a;*y=b;
    int z = 0;
    z = *x;
    *x = *y;
    *y = z;

}
int main()
{
    int a = 10;
    int b = 20;
    //printf("%p\n", &a);//00BAF7DC
    //printf("%p\n", &b);//00BAF7D0
    printf("交换之前a=%d,b=%d\n", a, b);
    //swap(a,b);//传值调用    实参     形参是实参的临时拷贝,形参的改变不会影响实参
    swap1(&a, &b);//传址调用
    printf("交换之后a=%d,b=%d\n", a, b);
    return 0;
}

/
//11.指针访问数组
#include<stdio.h>
int main()
{
    int arr[10] = { 0 };
    printf("%d\n", sizeof(arr));//40
    //1.sizeof内部单独放一个数组名的时候,数组名表示整个数组的大小
    //2.&数组名:表示整个数组的地址
    //3.其他所有数组名表示首元素地址
    printf("%d\n", sizeof(arr[0]));//4
    printf("%p\n", &arr[0]);//012FFC20//数组首元素地址
    printf("%p\n", &arr[0]+1);//int*类型,012FFC24
    printf("%p\n", arr);//012FFC20//数组名也是首元素地址
    printf("%p\n", arr+1);//int*类型,012FFC24
    printf("%p\n", &arr);//012FFC20//整个数组的地址
    printf("%p\n", &arr+1);//加了40个字节   跳过了一整个数组
    return 0;
}
//数组在内存中是连续存放的,所以可以通过指针来访问数组

#include<stdio.h>
int main()
{
    int arr[10] = { 0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    int* p = arr;
    for (int i = 0; i < sz; i++)
    {
        scanf("%d", p + i);//本身就是地址
    }
    for (int i = 0; i < sz; i++)
    {
        printf("%d ", *(p + i));
        //printf("%d ",arr[i]);
        //printf("%d ", *(arr + i));
        //arr[i] == *(arr+i)==i[arr](不推荐);
    }
    return 0;
}

#include<stdio.h>
void test(int arr[])//int* arr
{
    //sizeof(arr);是arr地址的大小    x86环境下int*类型的是4个字节
    int sz = sizeof(arr) / sizeof(arr[0]);
    printf("%d\n", sz);//1
}
int main()
{
    int arr[10] = { 0 };
    //数组传参时传的并非是数组,而是首元素地址
    test(arr);
    return 0;
}


/
//12.
//冒泡排序
//思想:相邻的两个元素比较,如果不满足顺序就交换
#include<stdio.h>
int  bubblesort(int* arr,int sz)
{
    for (int i = 0; i < sz-1; i++)
    {
        int flag = 1,count=0;
        for (int j = 0; j <sz-1-i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                count++;
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
                flag = 0;
            }
        }
        if (flag)
        {
            break;
        }
    }
}
int main()
{
    int arr[] = {9,8,7,6,5,4,3,2,1,0};
    int sz = sizeof(arr) / sizeof(arr[0]);
    int sum=bubblesort(arr, sz);
    for (int i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("%d", sum);//打印交换了几次
    return 0;
}

/
//13.
//一级指针:char*c   int* pi  double*pd
//二级指针:
#include<stdio.h>
int main()
{
    int a = 10;
    int* p = &a;//取的是a的地址
    int** pp = &p;//前面的int*是p的类型,后面的*是说明是pp是指针变量//二级指针
    //int*** ppp = &pp;//三级指针  很少
    printf("%d\n", **pp);//10
    return 0;
}


///
//14.
//指针数组:是数组
//整形数组:存放整形的数组
//字符数组:存放字符的数组
//指针数组:存放指针的数组,每个元素的类型是指针  //如int* arr[]    float* arr[]
// 
// 
// 
//指针数组模拟实现二维数组:
#include<stdio.h>
int main()
{
    int arr1[] = { 1,2,3,4,5 };
    int arr2[] = { 2,3,4,5,6 };
    int arr3[] = { 3,4,5,6,7 };

    int* arr[3] = { arr1,arr2,arr3 };
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            printf("%d ", arr[i][j]);//*(*(arr+i)+j)==arr[i][j]
        }
        printf("\n");
    }

    return 0;
}

/
//15.
//字符指针:
#include<stdio.h>
int main()
{
    //常量字符串无法修改
    const char* p = "abcdef";//将第一个字符的地址存放在p之中  相当于p[]
    printf("%c\n", *p);
    printf("%c\n", "abcdef"[3]);//d
    printf("%c\n", p[3]);

    return 0;
}


//列题
#include <stdio.h>
int main()
{
    char str1[] = "hello bit.";//两个数组
    char str2[] = "hello bit.";

    const char* str3 = "hello bit.";//常量字符串 无法被修改
    const char* str4 = "hello bit.";//内存中没有必要再创建一个相同的字符串,所以地址相同

    if (str1 == str2)//数组名表示首元素地址    两个独立的数组地址不相同
        printf("str1 and str2 are same\n");
    else
        printf("str1 and str2 are not same\n");//对

    if (str3 == str4)
        printf("str3 and str4 are same\n");//对
    else
        printf("str3 and str4 are not same\n");

    return 0;
}

/
//16.数组指针:
//整形指针:指向整形的指针
//字符指针:指向字符的指针
//数组指针:指向数组的指针:是一种指针!

//整形指针变量:存放的是整形的地址
//字符指针变量:存放的是字符的地址
//数组指针变量:存放的是数组的地址
#include<stdio.h>
int main()
{
    int n = 100;
    int* pn = &n;

    char ch = 'w';
    char* pc = &ch;

    //p旁边放*和[]时,p首先和[]结合;
    int* p1[10];//p1是数组,有十个元素,类型是int*,所以p1是指针数组
    int(*p2)[10];//p2是指针,指针指向的是数组,数组有十个元素,每个元素的类型是int,所以p2是数组指针

    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int* parr1 = &arr[0];
    int* parr2 = arr;//首元素的地址
    int (*parr3)[10]=&arr;//取出的是数组的地址//parr3是数组指针
    printf("%p\n", parr3 + 1);//跳过40个字节
    //parr3==&arr      *parr3==arr   (*parr3)[7]==arr[7]
    //int (* )[]是数组指针类型的
    return 0;
}

//17.
//二维数组传参的本质
// 
// 
//实参传arr
//形参接收用int arr[3][5]或int (*arr)[5]
//1.写成数组是为了方便理解
//2.写成指针是因为数组传参本质是传地址
// 
//二维数组的地址是第一行的地址
// arr+1为第二行   
// arr+2为第三行
//第一行的地址等于首元素地址


/
//18.
//函数指针变量:存放函数的地址
//函数名和&数组名都是函数的地址
#include<stdio.h>
int add(int x, int y)
{
    return x + y;
}
int main()
{
    printf("%p\n", &add);//00D813D4
    printf("%p\n", add);//00D813D4
    int (*pf)(int,int)=&add;//pf就是函数指针变量    相当于pf中存放了add的地址
    //(*pf)就相当于是add
    int(*pf2)(int, int) = add;
    int ret = add(3, 5);
    int ret2 = (*pf)(4,9);
    int ret3 = (*pf2)(2, 1);
    int ret4 = pf(2, 1);//可以不加*,直接用地址

    return 0;
}


//#include<stdio.h>
//char* test(int a, char c)
//{
//    return NULL;
//}
//int main()
//{
//    char* (*pt)(int, char) = test;
// 
// //char*(*)(int,int)函数指针类型
// 
//    return 0;
//}
// 
// 列题1:
// (*(void (*)())0)();//函数调用
// 
// 
// void(*)()是函数指针类型
// (int)3.14强制类型转化
// (void(*)())0将0强制类型转化成地址类型
//*(void(*)())0//解引用,调用(void(*)())0这块地址的函数
// 
// 
// 
//列题2:
//void (* signal(int,void(*)(int) )(int)//函数声明
// 
//void (*                         )(int)//函数指针类型
//signal是一个函数
//参数有有两个,一个是int,另一个是函数指针类型,返回类型是void
//
//
//typedef  重命名  将复杂的名字简单化
//typedef unsigned int uint; 
//typedef int(*parr_t)[10];//数组指针类型重命名为parr_t
// 
// 
//typedef void(*pf_t)(int);//函数指针类型重命名为pf_t
//void (* signal(int,void(*)(int) )(int)==pf_t  signal(int,pf_t)
// 
//
//函数的定义:
//int add(int x, int y)
//{
//    return x + y;
//}
//函数的声明
//int add(int x, int y);
//int add(int ,int );
//函数调用
//add(2,3);


/
//19.
//函数指针数组
//char* arr[5];//字符指针数组
//int* arr[6];//整形指针数组
//int(*pf[])(int,int);//函数指针数组
#include<stdio.h>
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 (*pf)(int, int) = add;
    int(*pfarr[])(int, int) = { add,sub,mul,div };//函数指针数组
    //                           0   1   2    3
    for (int i = 0; i < 4; i++)
    {
        int ret=pfarr[i](6, 2);
        printf("%d ", ret);
    }
    return 0;
}
//实现一个计算器
#include<stdio.h>
void menu()
{
    printf("**************************\n");
    printf("****1.add        2.sub****\n");
    printf("****3.mul        4.div****\n");
    printf("****0.exit            ****\n");
    printf("**************************\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 main()
{
    int a, b;
    int ret;
    int input = 0;
    do
    {
        menu();
        //这里的函数指针数组 我们称为转移表;
        int (*pfarr[])(int, int) = {NULL,add,sub,mul,div };
        printf("请输入:");
        scanf("%d", &input);
        if (input == 0)
        {
            printf("退出计算器\n");
        }
        else if (input >= 1 && input <= 4)
        {
            printf("请输入两个操作数:");
            scanf("%d%d", &a, &b);
            ret=pfarr[input](a, b);
            printf("%d\n", ret);
        }
        else
        {
            printf("输入错误,请重新选择\n");
        }
        //switch代码过冗余
        //switch (input)
        //{
        //case 1:
        //    printf("请输入两个操作数:");
        //    scanf("%d%d", &a, &b);
        //    ret=add(a, b);
        //    printf("%d\n", ret);
        //    break;
        //case 2:
        //    printf("请输入两个操作数:");
        //    scanf("%d%d", &a, &b);
        //    ret = sub(a, b);
        //    printf("%d\n", ret);

        //    break;
        //case 3:
        //    printf("请输入两个操作数:");
        //    scanf("%d%d", &a, &b);
        //    ret = mul(a, b);
        //    printf("%d\n", ret);

        //    break;
        //case 4:
        //    printf("请输入两个操作数:");
        //    scanf("%d%d", &a, &b);
        //    ret = div(a, b);
        //    printf("%d\n", ret);
        //    break;
        //case 0:
        //    printf("退出计算器\n");
        //    break;
        //default:
        //    printf("输入错误,请重新选择\n");
        //    break;
        //}

    } while (input);
    return 0;
}

/
//20
//函数指针的用途:
// 1.回调函数
//没有直接调用函数,通过传地址找到要调用的函数

#include<stdio.h>
void menu()
{
    printf("**************************\n");
    printf("****1.add        2.sub****\n");
    printf("****3.mul        4.div****\n");
    printf("****0.exit            ****\n");
    printf("**************************\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;
}
void calc(int (*pf)(int, int))
{
    int a, b;
    int ret;
    printf("请输入两个操作数:");
    scanf("%d%d", &a, &b);
    ret = pf(a, b);
    printf("%d\n", ret);
}
int main()
{
    
    int input = 0;
    do
    {
        menu();
        //这里的函数指针数组 我们称为转移表;
        int (*pfarr[])(int, int) = { NULL,add,sub,mul,div };
        printf("请输入:");
        scanf("%d", &input);
        
        switch (input)
        {
        case 1:
            calc(add);
            break;
        case 2:
            calc(sub);
            break;
        case 3:
            calc(mul);
            break;
        case 4:
            calc(div);
            break;
        case 0:
            printf("退出计算器\n");
            break;
        default:
            printf("输入错误,请重新选择\n");
            break;
        }

    } while (input);
    return 0;
}
//2.
//qsort排序:可以排序任意数据
//void qsort(void* base//指针//base指向要排序的数组的第一个元素
//           siza_t num//待排序的个数
//           siza_t size//每个元素的大小
//           int (*compar)(const void* p1,const void* p2)//函数指针//比较两个元素p1 p2
//                                                如果p1>p2则返回>0的数,p1==p2,则返回0.
// );
//qsort()排序整数
//结构体数据无法用><=来比较
#include<stdio.h>
#include<stdlib.h>
int cmp_int(const void* p1, const void* p2)
{
    return *(int*)p1 - *(int*)p2;
}
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr, sz, sizeof(int), cmp_int);
    return 0;
}
//qsort排序结构体数据
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stu
{
    char name[20];
    int age;
};
int cmp_stu_by_age(const void* p1, const void* p2)
{
    return ((struct stu*)p1)->age - ((struct stu*)p2)->age;
}
int cmp_stu_by_name(const void* p1, const void* p2)
{
    return strcmp(((struct stu*)p1)->name ,((struct stu*)p2)->name);
}
void test2()
{
    struct stu arr[] = { {"zhangsan",28},{"lisi",19} ,{"wuangwu",20}};
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
    for (int i = 0; i < sz; i++)
    {
        printf("%d ",arr[i].age);
    }
    
}
int main()
{
    test2();
    return 0;
}

//设计和实现排序任意元素(冒泡排序)
#include<stdio.h>
int cmp_int(const void* p1, const void* p2)
{
    return *(int*)p1 - *(int*)p2;
}
void Swap(char* buf1, char* buf2, size_t width)
{
    for (int i = 0; i < width; i++)
    {
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}
void bubblesort(int* base, size_t sz, size_t width, int(*cmp)(const void* p1, const void* p2))
{
    for (int i = 0; i < sz - 1; i++)
    {
        for (int 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 main()
{
    int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubblesort(arr, sz,sizeof(arr[0]),cmp_int);
    for (int i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

//设计和实现结构体任意元素(冒泡排序)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stu
{
    char name[20];
    int age;
};
int cmp_int_age(const void* p1, const void* p2)
{
    return ((struct stu*)p1)->age -((struct stu*)p2)->age;
}
int cmp_int_name(const void* p1, const void* p2)
{
    return strcmp(((struct stu*)p1)->name , ((struct stu*)p2)->name);
}
void Swap(char* buf1, char* buf2, size_t width)
{
    for (int i = 0; i < width; i++)
    {
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}
void bubblesort(void* base, size_t sz, size_t width, int(*cmp)(const void* p1, const void* p2))
{
    for (int i = 0; i < sz - 1; i++)
    {
        for (int 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 main()
{
    struct stu arr[] = { {"zhangsan",18},{"lisi",20},{"wangwu",30}};
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubblesort(arr ,sz, sizeof(arr[0]), cmp_int_age);
    bubblesort(arr, sz, sizeof(arr[0]), cmp_int_name);
    for (int i = 0; i < sz; i++)
    {
        printf("%d %s\n", arr[i].age,arr[i].name);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值