记录一个指针问题(内存空间的初始化)

2024-04-06 18:08

本文主要是介绍记录一个指针问题(内存空间的初始化),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先正确理解一下例子。 

  void test(){
        char *str[]={"welcome","to","fortemedia","Nanjing"};  
        char * * p=str+1;     //p指向 "to"字符串地址  

        printf("%s\n",str[0]);  
        printf("%s\n",str[1]);  
        printf("%s\n",str[2]);  
        printf("%s\n",str[3]);  

        printf("p==%x\n", p);
        printf("str[0]==%x\n", str[0]);
        printf("str[1]==%x\n", str[1]);
        printf("str[2]==%x\n", str[2]);
        printf("str[3]==%x\n", str[3]);
        printf("**str==%x\n", &str);
        printf("*p=%s\n", *p);
        str[0]=(*p++) +2;          //str[0]指向'\0';           然后p后移 p=str[2]  
        str[1]=*(p+1);            //p+1后 p+1 = str[3];   然后 str[1] = str[3]           
        str[2]=p[1]+3;             //str[2]指向str[3]的从0开始数的第三个 str[2]指向"jing"地址  
        str[3]=p[0]+(str[2]-str[1]);  //str[3]指向从p[0]开始(也就是*p,也就是str[2])的 偏移量为(str[2]-str[1])的地址~ str[2]指向"jing",str[1]指向str[3],也就是"Namjing",所以str[3]指向"jing"的"g"地址  
        printf("%s\n",str[0]);  
        printf("%s\n",str[1]);  
        printf("%s\n",str[2]);  
        printf("%s\n",str[3]);  
    }


main函数中首先定义

 char *p[DATA_LENGTH] ; // 定义一个指针数组。

 char name[23] = "tian";// 定义一个字符数组。

    init_data(p);   // 初始化指针数组
    printf("init done\n");
    show(p);// 初始化指针数组的数组
    printf("show done0==%s\n",p[0]);// p[0] 可以看作是数组的第一个数据。
    CountStrLen(p[0]);// 计算初始化数组的第一个数据的字符串长度


void init_data(char **p){  // 参数传入二维指针

    int i;
    for(i =0;i< DATA_LENGTH;i++)
    {
        printf("init data==%d\n",i);
        if(NULL==(p[i]=(char*)malloc(sizeof(char)*10)))  // 循环遍历动态申请空间
        {
            perror("error...");
            exit(1);
        }else
        {
            memset(p[i],0,sizeof(char)*10); // 初始化数组的值为0
            printf("init data==%s\n",p[i]);
        }
    }
}


正确的做法(这个函数有冗余代码)

void show(char **p){  // 参数传入二维指针

    int i;
    for(i = 0;i<DATA_LENGTH;i++){

        char *tmp;

        printf("show i==%d\n",i);
        if(NULL != (tmp=(char*)malloc(sizeof(char)*10)))
        {
            memcpy(tmp,"tian",5);  // 将tmp指向 tian 字符串的首地址
            memcpy(p[0],tmp,5); // 给p[0] 所指的数据空间赋值为 “tian”
            free(tmp); // 释放临时空间,切记,malloc 和free 一定同时出现
            printf("the data%d==,%s\n",i,p[i]);
        }
    }

错误的做法

void show(char **p){  // 参数传入二维指针

    int i;
    for(i = 0;i<DATA_LENGTH;i++){

        char *tmp;

        printf("show i==%d\n",i);
        if(NULL != (tmp=(char*)malloc(sizeof(char)*10)))
        {

            *tmp =“tian”;// 本身定义常量字符串他就是一段地址,也就是后期不能做修改。

            p[i] =tmp; // 将p[i]  又指向了一段常量地址。

            free(tmp); // 释放临时空间,切记,malloc 和free 一定同时出现
            printf("the data%d==,%s\n",i,p[i]);  // 打印没有问题,p[i]  一直是 tian
        }
    }

// 计算字符串的长度

    size_t CountStrLen(char *p){
        int i;
        size_t lenth=0;
        printf("p==%s\n",p);
        for(i =0 ; *p != '\0' ;i++){
            p++;
            lenth++;

            printf("length==%d,p[i]==%s\n",lenth,p);
        }
        printf("length==%d\n",lenth);
        return lenth;
    }


总结:

1. 指针所指向的内存地址空间,需要memcpy ,strcpy 去初始化。

2. 在错误的方法中在main 打印p[0] 没有错,他打印的是“tian”字符串,只能是巧合,凑巧申请的。

3. 全局的指针指向了一个局部的地址空间,当函数运行结束,局部的地址空间被释放,所以全局的指针指向了一段被释放的地址空间。

4. 以后若使用赋值,采用memcpy ,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。



这篇关于记录一个指针问题(内存空间的初始化)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/880489

相关文章

Linux部署中的文件大小写问题的解决方案

《Linux部署中的文件大小写问题的解决方案》在本地开发环境(Windows/macOS)一切正常,但部署到Linux服务器后出现模块加载错误,核心原因是Linux文件系统严格区分大小写,所以本文给大... 目录问题背景解决方案配置要求问题背景在本地开发环境(Windows/MACOS)一切正常,但部署到

MySQL磁盘空间不足问题解决

《MySQL磁盘空间不足问题解决》本文介绍查看空间使用情况的方式,以及各种空间问题的原因和解决方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录查看空间使用情况Binlog日志文件占用过多表上的索引太多导致空间不足大字段导致空间不足表空间碎片太多导致空间不足临时表空间

Mybatis-Plus 3.5.12 分页拦截器消失的问题及快速解决方法

《Mybatis-Plus3.5.12分页拦截器消失的问题及快速解决方法》作为Java开发者,我们都爱用Mybatis-Plus简化CRUD操作,尤其是它的分页功能,几行代码就能搞定复杂的分页查询... 目录一、问题场景:分页拦截器突然 “失踪”二、问题根源:依赖拆分惹的祸三、解决办法:添加扩展依赖四、分页

Java中InputStream重复使用问题的几种解决方案

《Java中InputStream重复使用问题的几种解决方案》在Java开发中,InputStream是用于读取字节流的类,在许多场景下,我们可能需要重复读取InputStream中的数据,这篇文章主... 目录前言1. 使用mark()和reset()方法(适用于支持标记的流)2. 将流内容缓存到字节数组

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

基于Spring Boot 的小区人脸识别与出入记录管理系统功能

《基于SpringBoot的小区人脸识别与出入记录管理系统功能》文章介绍基于SpringBoot框架与百度AI人脸识别API的小区出入管理系统,实现自动识别、记录及查询功能,涵盖技术选型、数据模型... 目录系统功能概述技术栈选择核心依赖配置数据模型设计出入记录实体类出入记录查询表单出入记录 VO 类(用于

解决Failed to get nested archive for entry BOOT-INF/lib/xxx.jar问题

《解决FailedtogetnestedarchiveforentryBOOT-INF/lib/xxx.jar问题》解决BOOT-INF/lib/xxx.jar替换异常需确保路径正确:解... 目录Failed to get nested archive for entry BOOT-INF/lib/xxx

解决hive启动时java.net.ConnectException:拒绝连接的问题

《解决hive启动时java.net.ConnectException:拒绝连接的问题》Hadoop集群连接被拒,需检查集群是否启动、关闭防火墙/SELinux、确认安全模式退出,若问题仍存,查看日志... 目录错误发生原因解决方式1.关闭防火墙2.关闭selinux3.启动集群4.检查集群是否正常启动5.

idea Maven Springboot多模块项目打包时90%的问题及解决方案

《ideaMavenSpringboot多模块项目打包时90%的问题及解决方案》:本文主要介绍ideaMavenSpringboot多模块项目打包时90%的问题及解决方案,具有很好的参考价值,... 目录1. 前言2. 问题3. 解决办法4. jar 包冲突总结1. 前言之所以写这篇文章是因为在使用Mav

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3