3.30指针笔记

本文详细介绍了C语言中的指针概念,包括指针变量存储地址、不同类型的指针、指针运算、指针与数组、字符串处理、多级指针以及函数指针的使用。此外,还讨论了指针在排序算法如快速排序中的应用,以及如何处理结构体数组排序的问题。
摘要由CSDN通过智能技术生成

 指针是什么?

 

通过地址我们可以找到所需要的变量单元

指针变量是用来存放地址的变量int a =10;int *p = &a;

类型为int *,在32位机器上是4个字节,在64位机器上是8个字节

printf("%d",sizeof(char *));
printf("%d",sizeof(short *));
printf("%d",sizeof(int *));
printf("%d",sizeof(double *));//输出都为4
int a=0x11223344;
int* pa=&a;
char* pc=&a;
printf("%p",pa);
printf("%p",pc);
//结果都是一样的

所以基类型的区别在哪?

int* pa=&a;

*pa=0;//更改了四个字节的内存值,*p能访问4个字节

char* pa=&a;

*pa=0;//只改变了一个字节的内存值,*p能访问1个字节

--所以指针应该选择合适的类型去引用

指针类型决定了指针的步长(字节)

int main ()
{
    int a = 0x11223344;
    int* pa=&a;
    char* pc=&a;
    printf("%p",pa);//
    printf("%p",pa+1);//向后偏移了4个字节
    printf("%p",pc);
    printf("%p",pc+1);//向后偏移了1个字节
}

野指针

指针指向的位置是不可知的

int *p;//未指向明确的地址

*p = 20//未指向初始化后的地址,将20随机地址储存

指针越界访问也会导致野指针

指针指向的空间被释放

 检查指针的有效性

if(pa!=NULL)

{

}

指针的运算

int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int i = 0;
    int sz = sizeof(arr)/sizeof(arr[0]);
    int* p = arr;
    for(i=0; i<sz;i++)
    {
        printf("%d",*p);
        p=p+1;//p++同
    }
    return 0;
}

指针求字符串长度

int my_strlen(char* str)
{
    char* start =arr;
    char* end=arr;
    while(*end !='\0')
    {
        end++;
    }
    return end-start;
}

int main ()
{
    char arr[]="bit";
    int len = my_strlen(arr);
    printf("%d",len);
    return 0;
}

 二级指针

int main()
{
    int a =10;
    int* pa=&a;
    int** ppa =&pa;//ppa就是二级指针
}

指针数组==数组,存放指针的数组

 

 

数组指针==指针

int a=10;
int b=20;
int c=30;
int* arr[3]={&a,&b,&c};
int i=0;
for(i=0;i<3,i++)
{
    printf("%d",*(arr[i]));
}

字符指针

char ch = 'w';

char* p = &ch; 

char* p2="abcdef";//字符的值不可更改

数组指针--实际上是一个指针

int *p = NULL;//整型指针,指向整型的指针,可以存放整型的地址

int *pc=NULL//pc是字符指针,指向字符的指针,可以存放字符的地址

int arr[10]={1,2,3,4,5,6,7,8,9,10}

int(*p)[10]=&arr

 指向数组指针的指针

char * arr[5];

char*(*pa)[5]=&arr;

 

 用于二维数组

void print1(int arr[3][5],int x,int y)
{
    int i=0;
    int j=0;
    for(i=0;i<x;i++)
     {   for(j=0;j<y;j++)
            {
                printf("%d",arr[i][j]);
            }
    printf("\n");
     }
}

void print2(int(*p)[5],int x,int y)
{
    
    int i=0;
    int j=0;
    for(i=0;i<x;i++)
     {   for(j=0;j<y;j++)
            {
                printf("%d",*(*(p+i)+j));//p+i是找到这一行的地址,*解引用是真的找到了这一行的值,然后+j是找到第几列的地址,最后*解引用是找到了i行j列的值。
            }
    printf("\n");
     }
}

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为首元素地址
    print2(arr,3,5);
    return 0;
}

这里二维数组arr为首元素地址,指的是第一行的地址(想象为一维数组 )

四个printf结果一致

 

 

数组参数,指针参数

一维数组传参

 

二维数组传参

  二级指针传参--传一级指针的地址或二级指针

 

函数指针

是指向函数的指针


int Add(int x,int y)
{
    int z = 0;
    z= x+y;
    return z;
}

int main()
{
    int a = 10;
    int b = 20;
    printf("%d\n",Add(a,b));
    return 0;
}

  

 

 

函数指针的数组

int(*arr[4])(int ,int)={Add,Sub,Mul,Div}

用途:转移表

char* my_strcpy(char* dest,const char* src);
//写一个函数指针pf,能够指向my_strcpy
char* (*pf)(char*,const char*);

//写一个函数指针数组pfarr,能够存放4个my_strcpy函数指针的数组
char*(*pfarr[4])(char*,const cahr*);

写一个计算器

void menu()
{
    printf("*************************\n");
    printf("***1.add        2.sub****\n");
    printf("***3.mul        4.div****\n");
    printf("***5.xor        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 Xor(int x,int y)
{
    return x^y;
}
int main()
{
    int input = 0;
    int x=0;
    int y=0;
    int(*pfArr[6])(int,int)={0, Add,sub,Mul,Div,Xor};
//pfArr是一个数组指针,指针指向的数组有4个元素,
//指向的数组的每个元素的类型是一个函数指针int(*)(int,int)
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d",&input);
        if(input>=1&&input<=5)
        {
            printf("请输入两个操作数:>");
            scanf("%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);
}

 

 

 

qsort库函数---可以排任意类型的数据

(快速排序)void qsort(void *base,//排序对象

                                        size_t num,//元素个数

                                        size_t width,//每个元素的字节大小

                                        int(*cmp)(const void *e1,const void *e1));//是函数指针,两个参数                                                                                                        //是待比较的两个元素的地址

void* 类型的指针不能进行解引用操作,也不能进行++ --操作

#include <stdlib.h>
#include <stdio.h>

int cmp_int(const void* e1,const void* e2)
{
    return *(int*)e1-*(int*)e2;//比较两个整型值,返回1,0,-1
}
int main()
{
    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;
    for(i=0;i<sz;i++)
    {
        printf("%d ",arr[i]);
    }
return 0;
}

冒泡排序

 

#include <stdio.h>
bubble_sort(int arr[],int sz)
{
    int i,j;
    for(i=0;i<sz-1;i++)
    {
        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;
            }
        }
    
    }
}
int main()
{
    int arr[10]={9,8,7,6,5,4,3,2,1,0};
    int sz=sizeof(arr)/sizeof(arr[0]);
    bubble_sort(arr,sz);
    int i;
    for(i=0;i<sz;i++)
    {
        printf("%d ",arr[i]);
    }
return 0;
}

如何给结构体数组排序?

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*
void bubble_sort(void*base,int sz,int width,int (*cmp(void* e1,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);
            }
        }
    }
}

 

 

 

CMake是一个跨平台的构建系统,用于生成自动化构建脚本,适用于多种编程语言和操作系统。这里提供一个基本的CMake 3.30版本安装教程,假设你正在基于Ubuntu系统: 1. **检查更新**: 确保你的系统是最新的,打开终端,输入: ``` sudo apt update ``` 2. **安装依赖**: 安装一些必要的依赖,包括开发库和包管理工具: ``` sudo apt install build-essential curl software-properties-common ``` 3. **添加CMake存储库**: 对于非官方版本的CMake,如3.30,你需要从个人源或者官方网站添加存储库。例如,你可以访问CMake官网(https://cmake.org/download/)下载适合的版本,然后按照指示进行。以下是添加PPA的示例: ```bash sudo add-apt-repository ppa:ubuntu-toolchain-r/test ``` 4. **安装CMake 3.30**: 输入以下命令替换`<version>`为3.30的实际版本号: ``` sudo apt-get install cmake<version> ``` 5. **验证安装**: 安装完成后,运行: ``` cmake --version ``` 如果看到你刚刚安装的CMake 3.30版本,则安装成功。 6. **配置环境变量**: 为了方便后续使用,你可能还需要将CMake的bin目录添加到PATH中。编辑`~/.bashrc`或`~/.zshrc`文件: ``` export PATH=/usr/bin/cmake-3.30:$PATH ``` 保存并退出编辑器,然后运行: ``` source ~/.bashrc 或者 exec $SHELL ``` **注意事项**: - 这个教程假设你使用的是Ubuntu 18.04或更高版本,因为PPA支持这个版本。其他Linux发行版可能会有所不同。 - 官方网站上提供的二进制包可能不包含3.30版本,需查看官网下载页面获取。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值