c/c++:指针p+p-p*p/,数组a+1,指针减指针,指针实现strlen函数,指针的比较运算,指针数组,多级指针

news2024/11/19 19:35:57

c++:

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
【19】c/c++:万能指针,泛型指针,const int *p,int const *p,int *const p,const int *const p,指针与数组,p++,


文章目录

  • c++:
    • @[TOC](文章目录)
  • c/c++:指针p+p-p*p/
  • 数组名取地址+1
  • 指针+指针
  • 用指针实现strlen函数
  • 指针的比较运算
  • 指针数组
  • 多级指针
  • 总结

c/c++:指针p+p-p*p/

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

void f67(void)
{
    int a = 10;
    int b = 20;

    int* p = &a;
    //printf("%p\n", p/2);//不能乘除?
}

指针不能做乘除运算
你把地址乘除有啥意义
加减是可以的

前后挪动多少字节



void f67(void)
{
    int a = 10;
    int b = 20;

    int* p = &a;
    //printf("%p\n", p/2);//不能乘除?
    printf("%p\n", p + 2);//不能乘除?
    printf("%p\n", p - 2);//不能乘除?
}


int main(void)
{
    f67();

    system("pause");
    return 0;
}

在这里插入图片描述
数组中加减整数也是前后挪动一个位置
数组中说偏字节没用
就是挪动一个位置

在这里插入图片描述
在这里插入图片描述
左右移动地址
好说

数组名取地址+1

是啥?


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

    printf("%p\n", a);
    printf("%p\n", &a[0]);
    printf("%p\n", p+1);//这是取地址
    printf("%p\n", a+1);//这是取地址

    printf("%p\n", &a);//这是取地址
    printf("%p\n", &a+1);//这是取地址---很猛
}


int main(void)
{
    f68();

    system("pause");
    return 0;
}

在这里插入图片描述
发现了吗,&a+1,挪动了12个字节【即a数组大小】
a+1=p+1,是p+1挪动了一个字节而已,到下一个元素
而&a+1
是加整个数组的字节,p挪动到整个数组后面了

牛了这个
在这里插入图片描述
&a不是取数组首个地址【因为a=&a[0]】
而是整个数组的地址
所以你+1
加的是数组类型整个这么大的空间

指针+指针



void f69(void)
{
    int a = 10;
    int b = 20;

    int* p = &a;
    int* q = &b;

    //printf("%p\n", p+q);//不可以操作

    printf("%p\n", p);//可以操作
    printf("%p\n", q);//可以操作
    printf("%p\n", p-q);//可以操作
    
}

在这里插入图片描述
对于普通变量
指针可以减,不可以加
但是没意义

那要是数组呢?



void f70(void)
{//指针和数组
    int a[] = { 1,2,3,4,5,6,7,8,9,0 };
    int* p = &a[3];
    printf("%p\n", p);//可以操作
    printf("%p\n", a);//可以操作
    printf("%p\n", p - a);//可以操作
}

int main(void)
{
    f70();

    system("pause");
    return 0;
}

在这里插入图片描述
C=12=3个int自己

实际也是类型这么个差距
int是3个这里

再看

void f70(void)
{//指针和数组
    int a[] = { 1,2,3,4,5,6,7,8,9,0 };
    int* p = &a[2];
    printf("%p\n", p);//可以操作
    printf("%p\n", a);//可以操作
    printf("%p\n", p - a);//可以操作
}

偏移过的元素个数
在这里插入图片描述
数组中指针相减
是俩指针之间的元素的偏移个数

相加不允许哦

在这里插入图片描述
数组读完后,野指针p-a的话
就是整个数组的偏移个数,也是整个数组的大小
懂???

用指针实现strlen函数

非指针形式


int mystrlen(char str[]) {
    //传入字符数组
    //原来是
    int i = 0;
    while (str[i] != '\0') i++;

    return i;//统计结果返回
}

void f71()
{
    char str[] = "hello";
    int len = mystrlen(str);
    printf("%d\n", len);
}

int main(void)
{
    f71();

    system("pause");
    return 0;
}

在这里插入图片描述

现在需要你用指针实现


int mystrlen2(char str[]) {
    //传入字符数组
    //指针实现
    char* p = str;
    while (*p != '\0') p++;

    return p-str;//统计结果返回个数
}

void f71()
{
    char str[] = "hello";
    int len = mystrlen(str);
    int len2 = mystrlen2(str);
    printf("%d\n", len);
    printf("%d\n", len2);
}

int main(void)
{
    f71();

    system("pause");
    return 0;
}

字符串本质是字符数组
char类型的数组

我们把str的首地址赋给指针p
然后判断*p是否为\0
是则说明p已经来到了野指针的地方,p-str地址就是间隔char的个数,这就是我们要的字符串的长度
在这里插入图片描述

否则说明p还没有到字符串结尾,p++,挪动char的1个字节长度
在这里插入图片描述
如果这个代码写出来了
说明我们对指针的掌握已经很透了

美滋滋

函数的形参,在调用是,都是copy一份东西给它
函数内部就不用直接用实参

*p是解引用
左值是赋值,右值是获取内容
反正理解透了就好办了
p++在数组中是挪动类型个字节

指针的比较运算


void f72()
{

    int a[] = { 1,2,3,4,5,6,7,8,9,0 };
    int* p = a;
    if (p > a)
    {
        printf("p>a\n%p\n", p);//可以操作
        printf("%p\n", a);//可以操作
    }
    else if(p<a)
    {
        printf("p<a\n%p\n", p);//可以操作
        printf("%p\n", a);//可以操作
    }
    else
    {
        printf("p=a\n%p\n", p);//可以操作
        printf("%p\n", a);//可以操作
    }
}

p指向一个地址
a是一个地址
反正地址大小是16进制的比较

在这里插入图片描述


    int a1 = 10;
    int b = 20;
    //俩变量之间的地址没用没意义

int*指针类型
p指针变量
在这里插入图片描述
NULL等价于0地址
这个地址其实是操作系统不允许操作的地址

指针数组

之前我们搞的都是整型int数组
存整数

如果是指针数组呢?
存的是地址呗


void f73()
{
    int a = 10;
    int b = 20;
    int c = 30;

    int* p1 = &a;
    int* p2 = &b;
    int* p3 = &c;

    int* arr[] = { p1,p2,p3 };//整型地址
    //这就是指针数组,说白了就是房间号的地址
    for (size_t i = 0; i < 3; i++)
    {
        printf("%p ", *arr[i]);//解引用
    }
}

int main(void)
{
    f73();

    system("pause");
    return 0;
}

在这里插入图片描述
注意中,这个解引用是abc的16进制数哦,就是abc
地址p123我们下面打印

申明p和a们
在这里插入图片描述
然后定义指针数组arr

低地址到高地址
分别存p1,2,3
实际存的就是地址咯
在这里插入图片描述


void f73()
{
    int a = 10;
    int b = 20;
    int c = 30;

    int* p1 = &a;
    int* p2 = &b;
    int* p3 = &c;

    int* arr[] = { p1,p2,p3 };//整型地址
    //这就是指针数组,说白了就是房间号的地址
    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", *arr[i]);//解引用
        printf("%p ", arr[i]);//arr指针地址本身
    }
}

int main(void)
{
    f73();

    system("pause");
    return 0;
}

arr[i]是p123这仨地址
而*arr[i]是对这仨地址的解引用,取出这三地址内部的abc变量
懂?
在这里插入图片描述
这里引出了二级指针
为啥呢,你数组里面存了指针,指针又是别的地址
所以是一个间接过程,二级地址
即二级指针

之前说了
arr[0]==*(arr+0)
arr名就是一个指针地址,偏移0之后解引用
这是数组取东西的本质


void f73()
{
    int a = 10;
    int b = 20;
    int c = 30;

    int* p1 = &a;
    int* p2 = &b;
    int* p3 = &c;

    int* arr[] = { p1,p2,p3 };//整型地址
    //这就是指针数组,说白了就是房间号的地址
    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", *arr[i]);//解引用
        printf("%p ", arr[i]);//arr指针地址本身
    }

    //看arr[0]
    printf("\n%d ", *arr[0]);//解引用
    printf("%d ", *(*(arr+0)));//解引用
    printf("%d ", *(*(arr)));//解引用
    printf("%d ", *(*arr));//解引用
    printf("%d ", **arr);//解引用
}

一通变化之后
你发现是**arr
啥,2级指针
*arr是解引用内部地址
**arr是解引用这个地址代表的变量
2级指针

懂?

在这里插入图片描述
再看二维数组


void f74()
{
    int a[] = { 10,10 };
    int b[] = { 20 };
    int c[] = { 30 };

    int* p1 = a;
    int* p2 = b;
    int* p3 = c;

    int* arr[] = { p1,p2,p3 };//整型地址
    //这就是指针数组,说白了就是房间号的地址
    for (size_t i = 0; i < 3; i++)
    {
        printf("%d ", *arr[i]);//解引用
        printf("%p ", arr[i]);//arr指针地址本身
    }

    //看arr[0]
    printf("\n%d ", *arr[0]);//解引用
    printf("%d ", *(*(arr + 0)));//解引用
    printf("%d ", *(*(arr)));//解引用
    printf("%d ", *(*arr));//解引用
    printf("%d ", **arr);//解引用
}

int main(void)
{
    f74();

    system("pause");
    return 0;
}

在这里插入图片描述
在这里插入图片描述
说明二维数组也是二级指针
懂?

多级指针

一级指针是变量的地址

int a=10;
int*p=&a;//一级指针
int **p1= &p;//一级指针的地址,是二级指针
int ***p2=&p1;//二级指针的地址,是三级指针

二级指针是一级指针的地址
三级指针是二级指针的地址
在这里插入图片描述
int** p[]就是一个三级指针
存的是二级指针的地址,懂吧

在这里插入图片描述
三级指针解引用就是变量a本身
不管如何就是地址寻下一个地址
继续寻找下一个地址
最后找到真的东西即可

美滋滋

在这里插入图片描述


void f75()
{
    int a = 10;
    int* p = &a;
    int** pp = &p;
    int*** ppp = &pp;


    printf("%p\n", ppp);
    printf("%p\n", &pp);
    printf("%p\n", pp);
    printf("%p\n", &p);
    printf("%p\n", p);
    printf("%p\n", &a);
    printf("%d\n", ***ppp);
    printf("%d\n", **pp);
    printf("%d\n", *p);
    printf("%d\n", a);
}

int main(void)
{
    f75();

    system("pause");
    return 0;
}

在这里插入图片描述
懂了吧,反正几级指针
你就几级引用即可

多级指针,不能跳跃定义
因为要一连串找地址,就像链表一样,懂了吧


总结

提示:重要经验:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/451099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IMX6ULLPRO单独编译kernel+dtb内核模块以及uboot

目录 为什么编译驱动程序之前要先编译内核&#xff1f; 驱动程序要用到内核文件&#xff1a; 编译内核 编译安装内核模块 编译内核模块 安装内核模块到 Ubuntu 某个目录下备用 安装内核和模块到开发板上 Bootloader 介绍 编译 u-boot 镜像 为什么编译驱动程序之前要先编…

4.4 使用分组聚合进行组内计算

4.4 使用分组聚合进行组内计算 4.4.1 使用groupby方法拆分数据groupby方法的参数及其说明&#xff1a;groupby对象常用的描述性统计方法如下&#xff1a; 4.4.2 使用agg方法聚合数据agg函数和aggregate函数的参数说明1、使用agg求出当前数据对应的统计量2、使用agg分别求字段的…

X509证书中的Subject Public Key Info

SubjectPublicKeyInfo在TBSCertificate的第七项: 对于ECC id-ecPublicKey OBJECT IDENTIFIER :: { iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } id-ecPublicKey 是必须的 ECParameters :: CHOICE {namedCurve OBJECT IDENTIFIER -- implicitCurve NULL -…

java day10

第10章 创建Swing界面 10.1 Swing的特性10.1.1 标准对话框1. 确认对话框2. 输入对话框3.消息对话框4. 选项对话框 10.1.2 使用对话框10.1.3 滑块10.1.4 滚动窗格10.1.5 工具栏10.1.6 进度条10.1.7 菜单10.1.8 选项卡式窗格 10.1 Swing的特性 10.1.1 标准对话框 JOptionPane类…

HTML5 <rt> 标签、HTML5 <ruby> 标签

HTML5 <rt> 标签 实例 HTML5 <rt>标签用于表示为<ruby>标签中的注释内容。 一个 ruby 注释&#xff1a; <ruby> 漢 <rt> ㄏㄢˋ </rt> </ruby> 尝试一下 浏览器支持 IE 9、Firefox、Opera、Chrome 和 Safari 支持 <rt> 标…

增广拍卖——二跳页下的拍卖机制探索

1. 引言 本文提出的方案已被WSDM 2023接收&#xff0c;论文&#xff1a;Boosting Advertising Space: Designing Ad Auctions for Augment Advertising&#xff0c; 下载&#xff1a;https://dl.acm.org/doi/abs/10.1145/3539597.3570381 信息流产品为了保障用户体验通常会严格…

关于python爬虫解析的问题

在进行Python爬虫解析时&#xff0c;需要注意以下事项&#xff1a; 1、良好的网站使用协议&#xff1a;需要遵守网站的robots.txt文件&#xff0c;以确保你的爬虫程序不会将网站拦截下来。 2、编码问题&#xff1a;需要正确设置HTTP头和解析器的编码&#xff0c;以确保爬虫程…

低代码开发重要工具:jvs-logic(逻辑引擎)可视化设计要素

逻辑引擎可视化的交互 可视化的服务编排是逻辑引擎的核心功能&#xff0c;逻辑引擎的界面可视化设计是为了方便用户使用和操作逻辑引擎而设计的。一个好的界面设计能够提高用户的工作效率和使用体验&#xff0c;同时也能增加软件的可靠性和可维护性。 以下是逻辑引擎界面可视化…

python数据分析综合案列--星巴克门店数据分析及可视化

本实训针对一组关于全球星巴克门店的统计数据&#xff0c;分析了在不同国家和地区以及中国不同城市的星巴克门店数量。 获取数据&#xff0c;数据放在directory.csv 这个案例主要分为以下几个部分&#xff1a; 数据清洗和预处理&#xff1a;使用 Pandas 进行数据清洗和预处理&…

windows下安装emscripten

Qt系列文章目录 文章目录 Qt系列文章目录前言一、Emscripten SDK介绍二、Emscripten SDK安装Get the emsdk repoEnter that directory 前言 由于Web端需要处理大量图像&#xff0c;大量图片的分辨率8k*8k&#xff0c;使用Canvas API&#xff08;画布&#xff09;是在HTML5中新…

(二)app自动化脚本录制回放

上一篇&#xff1a;(一)app自动化测试环境搭建&#xff08;maciosairtest &#xff09;_airtest环境搭建_要开朗的spookypop的博客-CSDN博客 注&#xff1a;后续都是用IOS设备来介绍自动化测试&#xff0c;安卓就不赘述了。 接上一篇&#xff0c;搭建好自动化测试环境后&#…

如何去阅读Java源码,我总结了18条心法

大家好&#xff0c;我是Martin。 这篇文章我准备来聊一聊如何去阅读开源项目的源码。 在聊如何去阅读源码之前&#xff0c;先来简单说一下为什么要去阅读源码&#xff0c;大致可分为以下几点原因&#xff1a; 最直接的原因&#xff0c;就是面试需要&#xff0c;面试喜欢问源码…

Docker实战笔记4-安装jenkins

转载请标明出处&#xff1a;http://blog.csdn.net/zhaoyanjun6/article/details/130318679 本文出自【赵彦军的博客】 文章目录 拉取 jenkins 镜像排查问题验证结果总结 拉取 jenkins 镜像 在官方镜像仓库查询 jenkins 镜像 https://hub.docker.com/r/jenkins/jenkins 拉取镜…

linux 安装php8.1 ZipArchive和libzip最新版扩展安装

1、概述 安装前咱们先看下我本地环境 [rootelk php8]# cat /etc/redhat-release Red Hat Enterprise Linux Server release 7.9 (Maipo) [rootelk php8]# [rootelk php8]# ./bin/php -v PHP 8.1.18 (cli) (built: Apr 17 2023 13:15:17) (NTS) Copyright (c) The PHP Group Z…

onnx手动操作

使用onnx.helper可以进行onnx的制造组装操作&#xff1a; 对象描述ValueInfoProto 对象张量名、张量的基本数据类型、张量形状算子节点信息 NodeProto算子名称(可选)、算子类型、输入和输出列表(列表元素为数值元素)GraphProto对象用张量节点和算子节点组成的计算图对象ModelP…

命令模式解读

问题引进 看一个具体的需求 1) 我们买了一套智能家电&#xff0c;有照明灯、风扇、冰箱、洗衣机&#xff0c;我们只要在手机上安装 app 就可以控制对这些家电工作。 2) 这些智能家电来自不同的厂家&#xff0c;我们不想针对每一种家电都安装一个 App&#xff0c;分别控制&…

HTTP相关知识

HTTP HTTP 是一种能够获取如 HTML 这样的网络资源的 protocol(通讯协议)。它是在 Web 上进行数据交换的基础&#xff0c;是一种 client-server 协议&#xff0c;也就是说&#xff0c;请求通常是由像浏览器这样的接受方发起的。一个完整的 Web 文档通常是由不同的子文档拼接而成…

苹果通讯录怎么备份?手机通讯录备份的方法看这里!

案例&#xff1a;手机通讯录怎么备份&#xff1f; 【友友们&#xff0c;想问下苹果手机的通讯录怎么样才能进行备份&#xff1f;可以解答我的疑惑吗&#xff1f;感谢&#xff01;】 在日常使用手机过程中&#xff0c;我们经常会遇到误删通讯录的情况。因此&#xff0c;备份通讯…

必须要知道的hive调优知识(上)

Hive数据倾斜以及解决方案 1、什么是数据倾斜 数据倾斜主要表现在&#xff0c;map/reduce程序执行时&#xff0c;reduce节点大部分执行完毕&#xff0c;但是有一个或者几个reduce节点运行很慢&#xff0c;导致整个程序的处理时间很长&#xff0c;这是因为某一个key的条数比其…

QT QPainter坐标变换绘图实例(五角星绘制)

1、绘制3个五角星的程序 创建一个基于 QWidget 的窗口的应用程序 &#xff0c;窗体上不放置任何组件。在 Widget 类的构造函数和paintEvent0事件中编写代码&#xff0c;代码内容如下。 Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(…