C++:指针

news2024/10/7 2:29:53

目录

1.指针

1.1指针三要素:

1.2修饰结构体struct 

1.3 Pointers of Pointers

1.4constant修饰 pointer

2.指针和数组

2.1.数组的地址是连续的

2.2pointer arithmetic:指针的代数运算 

2.3指针和数组的不同

3.内存分配:


1.指针

1.1指针三要素:

  • 运算符&:可以取对象或基本类型变量的地址。
  • 运算符*:可以获取指针指向的内容
int main(){
    //指针三要素
    int num = 10;
    int *p1 = NULL , *p2 = NULL;  //1.声明指针变量,必须初始化(NULL=整数0)
    p1 = # //2.取num地址,赋值给指针
    p2 = #
    cout << "p1的值:"<<p1 <<endl;
    cout<<"num = "<<num<<endl;

    *p1 = 20;  //3.利用指针修改num的值
    cout<<"num = "<<num<<endl;

    *p2 = 50;  //利用指针修改num的值
    cout<<"num = "<<num<<endl;

    cout << "p1的值:"<<p1 <<endl;
    cout << "p2的值:"<<*p2 <<endl;
    
    return 0;
}

1.2修饰结构体struct 

指针指向结构体:

  • p->member
  • (*p).member

 

    Student zhaoyan = { "yan",2000,true}; //实例化结构体
    Student *pStu = &zhaoyan;    //取这个结构体的地址

    strncpy(pStu->name,"Li",4);  //将pStu->name修改为Li
    pStu->born = 2021;
    (*pStu).born = 2002;
    pStu->male = false;

    cout << zhaoyan.name << " was born in " << zhaoyan.born 
         << ". Gender: " << (zhaoyan.male ? "male" : "female") << endl;
    
    //打印指针地址
    printf("address of zhaoyan: %p\n",pStu);           //C style p:输出指针地址
    cout<< "addres of zhaoyan: "<< pStu <<endl;       //C++ style
    cout<< "addres of zhaoyan: "<< &zhaoyan <<endl;       //C++ style
    cout<< "addres of zhaoyan.born: "<< &(zhaoyan.born) <<endl;       //C++ style

    cout<<"sizeof(pStu):" << sizeof(pStu) <<endl;

    return 0;

1.3 Pointers of Pointers

指针也是变量,也有地址:任何指针变量都占4个字节

    int num = 10;
    int *p = &num;
    int **pp = &p;  //指针的指针

    *(*pp) =20;
    cout<< "num=:"<<num<<endl;

    return 0;

1.4constant修饰 pointer

int main()
{
    int num = 1;
    int another = 2;
    
    //You cannot change the value that p1 points to through p1
    const int * p1 = &num; 指向的地址不变,即num不变
    *p1 = 3; //error 不能利用指针修改指针指向的值
    num = 3; //okay

    //You cannot change value of p2 (address)
    int * const p2 = &num; 内存里地址的值不变 ,即(*a)不变
    *p2 = 3; //okay  只能通过指针修改指针指向的值
    p2 = &another; //error

    //You can change neither
    const int* const p3 = &num;
    *p3 = 3; //error
    p3 = &another; // error

    return 0;
}

 例子:

为了函数求和等,传入只读的数

int foo(const char * p)
{
    // the value that p points to cannot be changed
    // play a trick?
    char * p2 = p; //syntax error 
    //...
    return 0;
}

2指针和数组

2.1.数组的地址是连续的

    Student stu[128];
    Student *p0 = &stu[0]; //主要中括号的优先级比&高
    Student *p1 = &stu[1];
    Student *p2 = &stu[2];
    Student *p3 = &stu[3];

    printf("p0=%p\n",p0);
    printf("p1=%p\n",p1);
    printf("p2=%p\n",p2);
    printf("p3=%p\n",p3);

    //相同的操作
    stu[1].born = 2000;
    p1->born =2000;

将数组名可以看作一个指针:
 

Student students[128];

printf("&students = %p\n", &students);
printf("students = %p\n", students);
printf("&students[0] = %p\n", &students[0]);

Student * p = students;
p[0].born = 2000; 
p[1].born = 2001;
p[2].born = 2002;

printf("students[0].born = %d\n", students[0].born);
printf("students[1].born = %d\n", students[1].born);
printf("students[2].born = %d\n", students[2].born);

2.2pointer arithmetic:指针的代数运算 

  • p+num  or  num+p points :指向数组p的第num个元素
  • p - num :指向第-num个数组

 给参数加()是为了优先级:更安全

//用宏来打印数组:宏是不能换行的
#define PRINT_ARRAY(array,n)\
for(int i=0;i<(n);i++)\                         //最好加一个()防止优先级
    cout<<"array["<<i<<"] = " <<(array)[idx] <<endl;

 

int main(){
    int numbers[4] = {0,1,2,3};
    PRINT_ARRAY(numbers,4);

    int *p = numbers+1;  //指向值为1的元素
    p++;    //指向值为2的元素

    cout << "numbers = " << numbers << endl;
    cout << "p = " << p << endl;

    *p =20;  //change 2 to 20
    *(p-1) = 20; //change 1to 10
    p[1] = 30;  //change 3 to 30
 
    PRINT_ARRAY(numbers,4);

    return 0;
}

注意:指针不能去了不该去的地方!这种错误最难找

小心越界:有时候会报错,有时不报错

int num = 0;
int * p = &num;
p[-1] = 2; //out of bound
p[0] = 3; //okay
*(p+1) = 4; //out of bound

 2.3指针和数组的不同

  • 数组是const指针
  • sizeof运算符指向指针将返回地址的大小(4或8)
  • 数组中所有元素的总大小可以通过sizeof运算符获得
int numbers[4] = {0, 1, 2, 3};
int * p = numbers;
cout << sizeof(numbers) << endl; //4*sizeof(int)
cout << sizeof(p) << endl; // 4 or 8
cout << sizeof(double *) << endl; // 4 or 8

3.内存分配:

在head上可以申请很大的内存使用, 

  •  分配未初始化存储的大小字节 malloc函数:。
void* malloc(size_t size)
  • 分配4个字节并将指针显式转换为(int*)
int *p1 = (int*)malloc(4)
  • Question:
int *p1 = (int*)malloc(3) 
//申请3个字节,但是int*需要4个字节
//但是不会报错,因为内存至少分配16个字节

内存的释放:

  • 必须显式释放动态分配的内存!:free函数
void free(void* ptr);
  • Question:
p = (int *) malloc(4 * sizeof(int));
// ...
p = (int *) malloc(8 * sizeof(int));
// ...
free (p);

内存泄漏:

案例:

void foo()
{
    int* p = (int*) malloc(sizeof(int));
    return;
}

上述的函数没有释放就return,在内存就找不到申请指针p的地址;必须在函数内释放

内存泄漏: 没有变量保留第一个地址。内存管理系统不会自动解除分配。浪费内存!

int main()
{
    int * p = NULL;
    
    p = (int *) malloc(4 * sizeof(int));
    // some statements
    p = (int *) malloc(8 * sizeof(int));
    // some statements
    free (p);
    // the first memory will not be freed

    for(int i = 0; i < 1024; i++)
    {
        p = (int *) malloc(1024 * 1024 * 1024);
    }
    printf("End\n");
    return 0;
}

C++中申请释放内存:

new:

   //allocate an int, default initializer (do nothing)
    int * p1 = new int; 
    //allocate an int, initialized to 0
    int * p2 =  new int();
    //allocate an int, initialized to 5
    int * p3 =  new int(5); 
    //allocate an int, initialized to 0
    int * p4 =  new int{};//C++11    
    //allocate an int, initialized to 5
    int * p5 =  new int {5};//C++11

    //allocate a Student object, default initializer
    Student * ps1 = new Student;
    //allocate a Student object, initialize the members
    Student * ps2 = new Student {"Yu", 2020, 1}; //C++11

    //allocate 16 int, default initializer (do nothing) 
    int * pa1 = new int[16];
    //allocate 16 int, zero initialized 
    int * pa2 = new int[16]();
    //allocate 16 int, zero initialized 
    int * pa3 = new int[16]{}; //C++11
    //allocate 16 int, the first 3 element are initialized to 1,2,3, the rest 0
    int * pa4 = new int[16]{1,2,3}; //C++11

    //allocate memory for 16 Student objects, default initializer
    Student * psa1 = new Student[16];
    //allocate memory for 16 Student objects, the first two are explicitly initialized
    Student * psa2 = new Student[16]{{"Li", 2000,1}, {"Yu", 2001,1}}; //C++11
    cout << psa2[1].name << endl;
    cout << psa2[1].born << endl;

delete:

    //deallocate memory
    delete p1;
    //deallocate memory
    delete ps1;

    //deallocate the memory of the array
    delete pa1;
    //deallocate the memory of the array
    delete []pa2;

    //deallocate the memory of the array, and call the destructor of the first element
    delete psa1;

    //deallocate the memory of the array, and call the destructors of all the elements
    //调所有的析构函数
    delete []psa2;  //最好用这种方法,删除数组结构体里所有内容

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

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

相关文章

内卷潮不断袭来,智己汽车主打高端市场有何胜算?

当前&#xff0c;新能源汽车赛道已进入白热化&#xff0c;2022年全年产销迈入700万辆规模&#xff0c;分别达到705.8万辆和688.7万辆&#xff0c;同比分别增长96.9%和93.4%&#xff0c;市占率为25.6%。在政策和市场的双轮驱动下&#xff0c;新能源汽车市场的竞争愈发激烈。为掌…

SpringCloudAlibaba和nacos整合sentinel的简单案例

文章目录1.简单代码1.1依赖1.2配置文件配置1.2.1项目yml配置文件1.2.2nacos配置文件1.2controller1.3 service2.sentinel下载运行3.运行验证nacos的安装部署SpringCloudAlibaba整合nacos1.简单代码 1.1依赖 SpringBoot 2.3.12.RELEASE SpringCloudAlibaba 2.2.8.RELEASE <…

自动识别查找特定的串口号 比如设备管理器中Modem属性里的串口 按这个方法可以获取设备管理器任意信息。C++

1.目标&#xff1a; 自动识别查找特定的串口号 2.注册表里搜串口号 设备管理器中所有的信息都在注册表中有&#xff0c;那么我直接在注册表里搜COM143。 搜到了这个&#xff0c;但这里有2个名称key相同的。后面193,192还是可能会变的&#xff0c;不方便精确识别。继续搜。 这…

从0到1一步一步玩转openEuler--01 openEuler操作系统介绍

1 openEuler操作系统介绍 openEuler是一款开源操作系统。当前openEuler内核源于Linux&#xff0c;支持鲲鹏及其它多种处理器&#xff0c;能够充分释放计算芯片的潜能&#xff0c;是由全球开源贡献者构建的高效、稳定、安全的开源操作系统&#xff0c;适用于数据库、大数据、云…

JVM 基础 - Java 垃圾回收机制

Java 垃圾回收机制一&#xff1a;哪些内存需要回收二&#xff1a;怎么定义垃圾1、引用计数算法2、可达性分析算法3、方法区的回收三&#xff1a;引用类型1、强引用2、软引用3、弱引用4、虚引用四&#xff1a;怎么回收垃圾1、垃圾回收算法标记 - 清除算法标记 - 整理算法标记 - …

STM32MP157开发板Linux+Qt项目实战:智慧家庭

stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器&#xff0c;集成2个Cortex-A7核和1个Cortex-M4 核&#xff0c;A7核上可以跑Linux操作系统&#xff0c;M4核上可以跑FreeRT…

第八章 idea集成github

第八章 idea集成github 第一节 给 IDEA 安装github插件 在IDEA中连接github需要在IDEA中github插件(如果有的话就不用安装了) 我这个是已经安装的状态 &#xff08;安装过程中按照提示安装即可&#xff09; 第二节 在 IDEA 中设置github账号 方式一 用户名密码登录 这种方…

HTTPS、SSH共享端口的--工具SSLH

目录 使用的环境 一、安装SSLH 二、配置nginx服务器 三、配置SSLH 三、启用并启动 sslh 服务以更新更改 四、测试 使用的环境 Ubuntu作为靶机&#xff0c;centos7做测试 一、安装SSLH 在Ubuntu上安装命令如下 $ sudo apt-get install sslh 安装 SSLH 时&#xff0c;将…

【LeetCode】最长同值路径 [M](二叉树)

687. 最长同值路径 - 力扣&#xff08;LeetCode&#xff09; 一、题目 给定一个二叉树的 root &#xff0c;返回 最长的路径的长度 &#xff0c;这个路径中的 每个节点具有相同值 。 这条路径可以经过也可以不经过根节点。 两个节点之间的路径长度 由它们之间的边数表示。 示…

阿里二面: BigKey、HotKey 问题严重,该如何 预防和解决

BigKey、HotKey是 日常生产中经常会碰到由于redis集群的不当访问&#xff0c;造成的线上问题。 而且&#xff0c;这也是常见的面试题。 在咱们社群的面试交流中&#xff0c;有很多小伙伴在面试网易、滴滴、京东等大厂的二面、三面中遇到了这个问题。 前段时间&#xff0c;有…

Hadoop基础之《(9)—整合HBase+Phoenix+Hive》

一、HBase简介 1、HBase定义 Apache HBase是以HDFS为数据存储的&#xff0c;一种分布式、可扩展的NoSQL数据库&#xff08;非关系型&#xff0c;以k,v的形式存储数据&#xff09;。 HBase可以认为是以HDFS为存储的数据库。 2、HBase数据模型 &#xff08;1&#xff09;HBase的…

Python---方法(普通方法,类方法,静态方法)

专栏&#xff1a;python 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;Python基础已经更新完&#xff0c;接下来是Python面向对象的知识点。 方法前言普通方法类方法静态方法总结前言 方法是什么&#xff1f; 一个类&#xff0c;它有特征&#xff0c;也有动作&#xff0…

华为OD机试(2023)真题目录(Java JS Python)

本专栏算法题均来自2023华为OD机考新题库。 本专栏算法题全部支持Java、JavaScript、Python语言实现。 注意&#xff1a;本专栏只包含新题库题目&#xff0c;不包含老题库题目。如果想同时拥有新、老题库全部题目&#xff0c;请订阅华为OD机试&#xff08;2022&2023&#…

c/c++开发,C++类的常用基本函数实现案例

一、C类的常用基本函数 C类的常用基本函数主要包括&#xff1a;默认构造函数&#xff0c;普通构造函数&#xff0c;拷贝构造函数&#xff0c;析构函数&#xff0c;赋值&#xff08;&#xff0c;运算符重载&#xff09;函数&#xff1a; 1.默认构造函数&#xff0c;在没有显式初…

苹果电脑怎么用移动硬盘ntfs?教你三招方法

苹果电脑怎么用移动硬盘ntfs&#xff1f;Mac可以正常读取NTFS外置设备上的文件&#xff0c;但是不能够正常往里面写入文件&#xff0c;同样不能对上面的文件进行编辑、删除、移动等&#xff0c;如果想要进行这些操作。 一、什么是NTFS NTFS是一个日志文件系统&#xff0c;这意…

稍纵即逝,读博期间要注意的事情 / 读博期间一定不要做的事

稍纵即逝&#xff0c;读博期间要注意的事情 读博期间一定不要做的10件事 tip&#xff1a;配图除了缓解文章疲劳&#xff0c;就没有其它意图了。 时间稍纵即逝&#xff0c;博士期间的科研时间其实非常紧张和短缺。对于刚入学的博士新生&#xff0c;尤其是直博生和长学制&#…

DMA驱动开发---认识DMA

DMA定义&#xff1a; DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预&#xff0c;通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。 DMA传输方式&#xff1a; DMA的作用就是实现数据的直接传输&#xff0c;而去掉了传统数…

Go 恶意软件增多,分析两个新发现的零检出样本

由于 Go 良好的跨平台特性&#xff0c;在多个操作系统与架构上都能运行&#xff0c;所以最近使用 Go 语言编写的恶意软件越来越多&#xff0c;每周都会发现大量的新样本。 在四月末&#xff0c;研究人员通过蜜罐发现了两个新的变种&#xff08;Backdoorit和 Caligula&#xff…

AOSP 8.0 系统启动概要

目录 一、Android 系统启动流程图 二、系统启动阶段 三、 系统重要进程 3.1 父进程 3.2 重量级进程 一、Android 系统启动流程图 备注&#xff1a;&#xff08;图片引用gityuan&#xff09; 二、系统启动阶段 step1. 启动电源及系统&#xff1a;电源按下后&#xff0c;引…

家庭网络WIFI相关知识

文章目录参考资料路由器的最大下载速率WFI协议WIFI工作频段和信道2.4GHZ频段5GHz频段双频路由器兼容性覆盖WIFI信号为什么总这么差&#xff1f;参考资料 WiFi穿墙完全指南&#xff1a;你的网速是由什么决定的&#xff1f; 路由器的最大下载速率 所谓的450M路由器中的“450M”…