c/c++:万能指针,泛型指针,const int *p,int const *p,int *const p,const int *const p,指针与数组,p++,

c/c++:万能指针,泛型指针,const int *p,int const *p,int *const p,const int *const p,指针与数组,p++,

2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,此时学会c++的话,
我所知道的周边的会c++的同学,可手握10多个offer,随心所欲,而找啥算法岗的,基本gg
提示:系列c++学习的基础和高阶知识,用于公司生产实践中,实实在在的公司部署产品要用的,因为c++速度快,
而java和Python速度慢,自然往硬件里面部署算法啥的,都得用c++或者c,因此本科学的c很重要,后来的Python或者java就没有那么重要了,
c/c++系列文章:
【1】c++:c语言优缺点,visual studio2019如何新建项目,写hello world程序
【2】c/c++:gcc安装,gcc编译hello world文件,system函数调用系统命令,sleep函数
【3】linux下gcc的编译过程和功能,预处理,编译,汇编,链接,.c预处理为.i文件.s文件.o文件.exe文件
【4】c/c++:windows平台下依赖的动态库,c底层是汇编语言,程序断点调试,反汇编,vs快捷键
【5】c/c++:数据类型,常量变量,标识符,有符号整型,无符号unsigned,字符类型,字符串类型,实数类型,浮点型,科学计数法
【6】c/c++:2进制、8进制、10进制、16进制和进制之间的转换,c语言输出匹配格式%
【7】c/c++:原码,反码,补码和常见的数据类型取值范围,溢出
【8】c/c++:类型限定符,printf输出格式,putchar,scanf,getchar
【9】c/c++:算术运算符,赋值运算,逻辑运算,比较运算,三目运算,逗号运算,数据类型转换
【10】c/c++:顺序结构,if else分支语句,do while循环语句,switch case break语句
【11】c/c++:for循环语句,分号不可省略,表达式可以省略,猜数字游戏,跳转语句continue,break,避免写goto
【12】c/c++:一维数组,初始化数组,循环打印数组,计算数组存储空间,数组元素个数,数组逆序算法
【13】c/c++:二维数组,数组的行数和列数求法sizeof,数组初始化不同形式,5个学生,3门功课,求学生总成绩和功课总成绩
【14】c/c++:visual studio的代码快捷键,VS设置自定义默认代码,使用快捷键
【15】c/c++:三维数组,字符数组和字符串,统计字符串中字符出现的频次,scanf输入空格,正则匹配表达式
【16】c/c++:gets(),fgets(),puts(),fputs(),strlen(),字符串拼接函数
【17】c/c++:函数的作用,分类,随机数,函数定义,调用,申明,exit()函数,多文件编程,防止头文件重复
【18】c/c++:指针,指针定义和使用,指针大小4字节,野指针,空指针*p=NULL


c/c++:万能指针,泛型指针:


void f58(void)
{
    int a = 10;
    void* p;//泛型万能指针--使用的时候类型具体化
    p = &a;

    printf("%d\n", *(int*)p);//p变量将其转化为int*
}

void*在使用时必须要强转为某种类型的指针
才能解引用
在这里插入图片描述

void f58(void)
{
int a = 10;
void* p;//泛型万能指针–使用的时候类型具体化
p = &a;

printf("%d\n", *(int*)p);//p变量将其转化为int*


char ch = 'a';
p = &ch;
printf("%c\n", *(char*)p);//p变量将其转化为int*

}

在这里插入图片描述
char*强转也是这样的
具体化数据类型
泛型在java中也是这么玩的

在这里插入图片描述

const关键字的作用

const修饰的变量只可读,不可改
const定义常量不靠谱
最好是用define

你看看这个,指针就能修改常量哦



void f59(void)
{
    //const
    const int a = 20;

    int* p = &a;
    *p = 200;
    printf("%d\n", a);
}

int main(void)
{
    f59();

    system("pause");
    return 0;
}

在这里插入图片描述
接下来,const修饰指针怎么说?

**const int p【const修饰p,p不可修改】
int const p【const修饰p,p不可修改】
int const p【const修饰p,p不可修改】
const int const p【const修饰p和p,p和
p不可修改】


void f60(void)
{
    int a = 10;
    int b = 10;
    const int* p = &a;//p可修改,不可以修改*p
    printf("%d\n", a);
    p = &b;
    //*p = 200;

   // const int* p
   
    //int const* p
    

    //int* const p
    

   // const int* p
}

void f61(void)
{
    int a = 10;
    int b = 10;
    int const * p = &a;//p可修改,不可以修改*p
    printf("%d\n", a);
    p = &b;
    //*p = 200;//所以int const *p=const int *p

    //int const* p


    //int* const p


   // const int* p
}

void f62(void)
{
    int a = 10;
    int b = 10;
    int* const p = &a;//p不可以修改,*p可修改
    printf("%d\n", a);
    //p = &b;
    *p = 200;//看const修饰谁?谁就不可以更改


    //int* const p


   // const int* p
}


void f63(void)
{
    int a = 10;
    int b = 10;
    const int* const p = &a;//p不可以修改,*p不可以修改
    printf("%d\n", a);
    //p = &b;
    //*p = 200;//看const修饰谁?谁就不可以更改


   // const int* const p
}

int main(void)
{
    f60();

    system("pause");
    return 0;
}

总之,被const修饰的部分,就不能修改。
在这里插入图片描述
内部不小心把是参照个字符串修改了怎么办?
最好就是内部操作不要改动人家传过来的地址空间。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原始字符串是不能修改的

数组名就是地址常量,它不可以被修改

数组名
要强化其概念
它是一个地址常量
,不可以修改,否则你的内容怎么搞?


void f64(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int b[3];

    //b = a;//不行,数组名是地址常量,是不可修改的名,它是地址
}

int main(void)
{
    f64();

    system("pause");
    return 0;
}

如果你想让b初始化赋值,怎么搞?

要么你for循环赋值
要么挨个指定b[i]=x;

今天搞一个绝招,指针被赋值


void f64(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int b[3];

    //b = a;//不行,数组名是地址常量,是不可修改的名,它是地址

    int* p = b;//b本身就是地址

    //for (size_t i = 0; i < 3; i++)
    //{
    //    printf("%d ", b[i]);
    //}

}

常量地址可以给变量指针赋值

然后我们取数组元素看看
for循环这么取
在这里插入图片描述


void f64(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int b[3];

    //b = a;//不行,数组名是地址常量,是不可修改的名,它是地址

    int* p = a;//b本身就是地址

    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", a[i]);
    }

}

在这里插入图片描述
&a[0]=a
取a[0]的本质是指针解引用
在这里插入图片描述
a[1]
是*(a+2)
加1就是int推4字节
在这里插入图片描述
所以
你用指针试试


void f64(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int b[3];

    //b = a;//不行,数组名是地址常量,是不可修改的名,它是地址

    int* p = a;//b本身就是地址

    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", a[i]);
        printf("%d ", *(a+i));
    }

}

在这里插入图片描述
牛逼
用p看看?


void f64(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int b[3];

    //b = a;//不行,数组名是地址常量,是不可修改的名,它是地址

    int* p = a;//b本身就是地址

    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", a[i]);
        printf("%d ", *(a+i));
        printf("%d ", *(p+i));
    }

}

在这里插入图片描述
因为p就是a
指针

记住这个结论
在这里插入图片描述
学了半天终于知道指针的作用了吧


void f64(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int b[3];

    //b = a;//不行,数组名是地址常量,是不可修改的名,它是地址

    int* p = a;//b本身就是地址

    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", a[i]);
        printf("%d ", p[i]);
        printf("%d ", *(a+i));
        printf("%d ", *(p+i));
    }

}

在这里插入图片描述
所以说
数组本身就是一个指针
卧槽1!1!
在这里插入图片描述

指针和数组还是有区别的

指针是变量
数组名是常量

sizeof(数组)是数组整体空间
而sizeof(指针)=4;固定不变


void f64(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int b[3];

    //b = a;//不行,数组名是地址常量,是不可修改的名,它是地址

    int* p = a;//b本身就是地址

    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", a[i]);
        printf("%d ", p[i]);
        printf("%d ", *(a+i));
        printf("%d ", *(p+i));
    }

    printf("\nsizeof(a):%d ", sizeof(a));
    printf("sizeof(p):%d ", sizeof(p));//指针



}

在这里插入图片描述
懂?
不太一样的哦

其实还有,取数值的时候
a[i]取过程中,a是不变的哦,常量
如果是p[i]
或者*(p+i)
p是变量,你解引用得到的是数组内部i那个数哦
p是变化的

p++
它是变量
p挪动到下一个位置了
在这里插入图片描述
在这里插入图片描述
你要是不用for循环
直接p++就完事了

指针p±的作用

//先看一个联系
    int a = 0x12345678;//内存地址,4字节

看它在地址中存在某个地址里面
存了这种16进制,上面高地址(存高位数),下面低地址(存低位数)
在这里插入图片描述

int* p = &a;//将p指向a的低地址

在这里插入图片描述


void f65(void)
{
    //先看一个联系
    int a = 0x12345678;//内存地址,4字节
    int* p = &a;//将p指向a的低地址
    printf("%p\n", *p);
}

在这里插入图片描述
*p就是解引用
读取其内容



void f65(void)
{
    //先看一个联系
    int a = 0x12345678;//内存地址,4字节
    char* p = &a;//将p指向a的低地址
    printf("%p\n", *p);
}

在这里插入图片描述
指针类型决定了你解引用读取内容时,读取的空间有多大

在这里插入图片描述
指针本身是地址,就4字节
指针类型决定读取时解引用空间的大小
懂?

在这里插入图片描述
所以说
咱们又总结一波,数据类型对指针的作用
间接引用:决定从指针开始,向后读取的空间大小,字节个数,与指针本身的4字节空间无关

来,咱们看看p和p+1



void f65(void)
{
    //先看一个联系
    int a = 0x12345678;//内存地址,4字节
    char* p = &a;//将p指向a的低地址
    printf("%p\n", *p);
    printf("%p\n", p);
    printf("%p\n", p+1);//这是地址增多少字节,看你前面类型
}

在这里插入图片描述
是不是,char类型的p,+1,确实是1字节,因为字符就是1字节空间
你再看看int类型的p呢


void f65(void)
{
    //先看一个联系
    int a = 0x12345678;//内存地址,4字节
    int* p = &a;//将p指向a的低地址
    printf("%p\n", *p);
    printf("%p\n", p);
    printf("%p\n", p+1);//这是地址增多少字节,看你前面类型
}

在这里插入图片描述
懂了吧
类型决定了指针往后读取的个数

p++跳动的范围是字节,而不是1
在这里插入图片描述
确实牛逼,当年大一压根就没学会指针
也没有老师讲这么细致

数组中指针p++操作

在这里插入图片描述


void f66(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int* p = a;//b本身就是地址

    /*for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", a[i]);
        printf("%d ", p[i]);
        printf("%d ", *(a + i));
        printf("%d ", *(p + i));
    }*/
    //还可以通过指针++直接访问数组缘故
    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", *p);
        p++;
    }
}

在这里插入图片描述
我自己改写出来了,直接解引用*p即可

在这里插入图片描述
不妨设arr首地址我0x00
p++后
p的值是0x04
懂?

在这里插入图片描述
这种p+++++
最后就是野指针了

如果通过*(p+i)
p永远都不会是野指针
p是固定的

如果p++,p+=1是会改变p的

自己领悟一番就明白了

通过指针访问数组给数组赋值

通过指针给它赋值好说
左值就是赋值
右值是取回


void f66(void)
{//指针和数组
    int a[] = { 1,2,4 };
    int* p = a;//b本身就是地址

    /*for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", a[i]);
        printf("%d ", p[i]);
        printf("%d ", *(a + i));
        printf("%d ", *(p + i));
    }*/
    //还可以通过指针++直接访问数组缘故
    for (size_t i = 0; i < 3; i++)
    {
        *(p + i) = 10;//赋值
    }
    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", *p);
        p++;
    }
}

在这里插入图片描述
easy

在这里插入图片描述
在这里插入图片描述


总结

提示:重要经验:

1)
2)学好c++,即使经济寒冬,手握10个大厂offer绝对不是问题!
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰露可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值