当前位置: 首页 > news >正文

Day 11

文章目录

    • 内存分区代码分析
    • 结构体
    • 结构体和指针
    • 技术细节
    • 小结

内存分区代码分析

返回栈区地址

#include<stdio.h>
int *fun()
{
        int a = 10;
        return &a;
}
int main()
{
        int *p =NULL;
        p = fun();
        *p = 100; //操作野指针指向的内存,err

        return 0;
}

 返回data区地址

#include<stdio.h>
int *fun()
{
        static int a = 10;
        return &a;//a不释放
}
int main()
{
        int *p = NULL;
        p = fun();
        *p = 100; //ok
        printf("*p = %d\n",*p);
        return 0;
}

值传递
 

#include<stdio.h>
#include<stdlib.h>
void fun(int *tmp)
{       
        tmp = (int *)malloc(sizeof(int));
        *tmp = 100;
}       
int main()
{       
        int *p = NULL;
        fun(p); //值传递,形参不会影响实参!!!
        printf("*p = %d\n",*p); //err//操作空指针指向的内存
        return 0;
}

值传递2
 

#include<stdio.h>
void fun(int *tmp)
{
        *tmp = 100;
}
int main()
{       
        int *p = NULL;
        p = (int *)malloc(sizeof(int));

        fun(p); //值传递
        printf("*p = %d\n",*p); //ok
        return 0;
}       

 返回堆区地址

#include<stdio.h>
#include<stdlib.h>
int *fun()
{
        int *tmp = NULL;
        tmp = (int*)malloc(sizeof(int));
        *tmp = 100;
        return tmp;
        //返回堆区地址,函数调用完毕,不释放
}
int main()
{
        int *p = NULL;
        p = fun();
        printf("*p = %d\n",*p); //ok

        //堆区空间,使用完毕,手动释放
        if(p != NULL)
        {
                free(p);
                p = NULL;
        }
        return 0;
}

结构体

结构体的基本操作

#include<stdio.h>
#include<string.h>
//定义一个结构体类型
//1、struct是关键字
//2、struct Student合起来才是结构体类型
//3、结构体内部定义的变量不能直接赋值
//4、结构体只用一个类型,没有定义变量前,是没有分配空间,没有空间,就不能赋值
struct Student
{
        int age;
        char name[50];
        int score;
};//有分号
int main()
{
        //定义结构体变量
        //1、类型名 变量名
        struct Student sru;//别忘了struct关键词

        //1、结构体变量初始化,和数组一样,要使用大括号
        //2、只有在定义时才能初始化
        struct Student sru2 = {18,"mike",60};

        struct Student tmp;

        //如果是普通变量,使用,点运算符
        tmp.age = 19;
        //tmp.name = "mike";//name成员是数组名,数组名是常量,不能修改
        strcpy(tmp.name,"mike");
        tmp.score = 60;

        //如果是指针变量,使用->
        //如果是指针,指针有合法指向,才能操作结构体成员
         struct Student *p;
         p = &tmp;
         p -> age = 18;
         strcpy(p->name,"mkie");
         p -> score = 60;

         //任何结构体变量都可用.或者->操作成员
         (&tmp)->age = 18;
         (*p).age = 18;
         p[0].age = 18;



        return 0;
}

结构体使用画图

结构体变量使用补充

#include<stdio.h>
struct Student
{
        int age;
        char name[50];
        int score;
}s1 = {18,"mike",60},s2;
struct
{
        int age;
        char name[50];
        int score;
}s3,s4;
int main()
{
        printf("%d,%s,%d\n",s1.age,s1.name,s1.score);
        return 0;
}

结构体数组
 

#include<stdio.h>
#include<string.h>
struct Student
{
        int age;
        char name[50];
        int score;
};
int main()
{
        struct Student s;

        struct Student a[5]; //结构体数组
        //操作元素
        a[0].age = 18;
        strcpy(a[0].name,"mike");
        a[0].score = 80;

        //操作某个元素地址
        (a+1)->age = 18;
        strcpy((a+1)->name,"jiang");
        (a+1)->score = 60;

        //操作元素
        (*(a+2)).age = 20;
        strcpy((*(a+2)).name,"fee");
        (*(a+2)).score = 59;

        struct Student *p = a;
        p[3].age = 21;
        strcpy(p[3].name,"xiang");
        p[3].score = 54;

        (p+4)->age = 22;
        strcpy((p+4)->name,"fei");
        (p+4)->score = 66;

        int i = 0;
        int n = sizeof(a)/sizeof(a[0]);
        for(i = 0;i < n;i++)
        {
                printf("%d,%s,%d\n",a[i].age,a[i].name,a[i].score);
        }
        return 0;
}
int main02()
{
        struct Student a1[5] =
        {
                {18,"mike",80},
                {18,"jiang",60},
                {20,"fee",59},
                {21,"xiang",54},
                {22,"fei",66}
        };
        struct Student a2[5] =
        {
                18,"mike",80,
                18,"jiang",60,
                20,"fee",59,
                21,"xiang",54,
                22,"fei",66
        };
        struct Student a3[5] =
        {18,"mike",80,18,"jiang",60,20,"fee",59,21,"xiang",54,22,"fei",66
        };
        
        //求平均分
        int i = 0;
        int n = sizeof(a1)/sizeof(a1[0]);
        int sum = 0;
        for(i = 0;i < n;i++)
        {
                sum+=a1[i].score;
        }
        printf("平均分: %d\n",sum)
        return 0;
}

结构体嵌套

#include<stdio.h>
#include<string.h>
struct Info
{
        int age;
        char name[50];
};
struct Student
{
        struct Info info;
        int score;
};
int main()
{
        struct Student s;
        s.info.age = 18;
        strcpy(s.info.name,"mike");
        s.score = 69;

        struct Student *p = &s;
        p->info.age = 18;
        strcpy(p->info.name,"mike");
        p->score = 69;

        struct Student tmp = {18,"mike",69};
        printf("%d,%s,%d\n",tmp.info.age,tmp.info.name,tmp.score);

        return 0;
}

结构体赋值

#include<stdio.h>
#include<string.h>
struct Student
{
        int age;
        char name[50];
        int score;
};
int main()
{
        int a = 10;
        int b;
        //把a的值赋给了b
        b = a;

        //1、相同类型的2个结构体变量可以相互赋值
        //2、尽管2个结构体变量的内容一样,但是2个变量是没有关系的独立内存
        struct Student s1 = {19,"mike",78};
        struct Student s2;
        s2 = s1;
        printf("%d,%s,%d\n",s2.age,s2.name,s2.score);

        return 0;
}

结构体值传递和地址传递区别
 

#include<stdio.h>
#include<string.h>
struct Student
{
        int age;
        char name[50];
        int score;
};
void setStu(struct Student tmp)
{
        tmp.age = 22;
        strcpy(tmp.name,"jiang");
        tmp.score = 66;
        printf("setStu %d,%s,%d\n",tmp.age,tmp.name,tmp.score);
}
int main()
{

        struct Student s1 = {19,"mike",78};
        setStu(s1);
        printf("%d,%s,%d\n",s1.age,s1.name,s1.score);

        return 0;
}

 

#include<stdio.h>
struct Student
{
        int age;
        char name[50];
        int score;
};
void fun(struct Student tmp)
{
        printf("%d,%s,%d\n",tmp.age,tmp.name,tmp.score);
}
void fun2(struct Student *p)
{
         printf("%d,%s,%d\n",p->age,p->name,p->score);
}

void fun3(const struct Student *p)
{
         printf("%d,%s,%d\n",p->age,p->name,p->score);
}
/*
void fun2(struct Student const *p)
{
         printf("%d,%s,%d\n",p->age,p->name,p->score);
}
*/
int main()
{
        struct Student s1 = {18,"mike",57};

        //fun(s1);
        fun2(&s1);
        fun3(&s1);
        return 0;
}

结构体和指针

指针指向栈区空间

#include<stdio.h>
#include<string.h>
struct Student
{
        int age;
        char name[50];
        int score;
};
int main()
{
        //定义一个结构体类型的指针
        struct Student *p;

        //在栈区定义一个结构体变量
        struct Student tmp;
        p = &tmp;

        p->age = 18;
        strcpy(p->name,"mike");
        p->score = 89;
        printf("%d,%s,%d\n",p->age,p->name,p->score);
        printf("%d.%s,%d\n",tmp.age,tmp.name,tmp.score);

        return 0;
}   


指针指向栈区空间

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Student
{
        int age;
        char name[50];
        int score;
};
int main()
{
        struct Student *p;

        //指针指向堆区空间
        p = (struct Student *)malloc(sizeof(struct Student));
        if(p == NULL)
        {
                printf("malloc err\n");
                return 0;
        }

        p -> age = 18;
        strcpy(p->name,"mike");
        p->score = 89;
        printf("%d,%s,%d\n",p->age,p->name,p->score);

        if(p != NULL)
        {
                free(p);
                p = NULL;
        }
        return 0;
}


非法使用内存导致的错误说明

#include<stdio.h>
#include<string.h>
struct Student
{
        int age;
        char name[50];
        int score;
};
struct Test
{
        char *str;
        int a;
        int b;
        int c;
};
int main01()
{
        struct Student s;
        s.age = 18;
        strcpy(s.name,"mike");
        s.score = 59;

        return 0;
}
int main()
{
        struct Test obj;
        strcpy(obj.str,"mike");//给str指向的内存拷贝内容
        printf("str = %s\n",obj.str);
        return 0;
}


成员指针指向data区或栈区

#include<stdio.h>
#include<string.h>

struct Student
{
        int age;
        char *name;
        int score;
};
//成员变量指针指向文字常量区的字符串
int main()
{
        struct Student s;
        s.age = 18;
        s.name = "mike"; //指针变量保存字符串常量的首地址
        s.score = 69;
        return 0;
}
#include<stdio.h>
#include<string.h>

struct Student
{
        int age;
        char *name;
        int score;
};
//成员变量指针指向栈区空间
int main()
{
        struct Student s;
        s.age = 18;

        char buf[100];
        s.name = buf; //指针变量保存字符串常量的首地址
                      
        strcpy(s.name,"mike");
        s.score = 69;
        printf("buf = %s\n",buf);
        return 0;
}


成员指针指向堆区空间

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Student
{
        int age;
        char *name;
        int score;
};
//成员变量指针指向堆区空间
int main()
{
        struct Student s;
        s.age = 18;

        // s.name = (char *)malloc((strlen("mikehelloworld")+1)*sizeof(char)); //char空间为1字节,可以忽略
        s.name = (char *)malloc(strlen("mikehelloworld")+1);

        strcpy(s.name,"mikehelloworld");
        s.score = 69;
        printf("%d,%s,%d\n",s.age,s.name,s.score);
        if(s.name != NULL)
        {
                free(s.name);
                s.name = NULL;
        }
        return 0;
}


结构体套一级指针

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Student
{
        int age;
        char *name;
        int score;
};
int main()
{
        struct Student *p;

        //给p分配内存
        p = (struct Student *)malloc(sizeof(struct Student));
        if(p == NULL)
        {
                printf("分配失败\n");
                return 0;
        }
        p->name = (char *)malloc(strlen("mike")+1);

        p->age = 18;
        strcpy(p->name,"mike");
        p->score = 54;

        printf("%d,%s,%d\n",p->age,p->name,p->score);

        //先释放name
        if(p->name != NULL)
        {
                free(p->name);
                p->name = NULL;
        }

        //再释放p
        if(p != NULL)
        {
                free(p);
                p = NULL;
        }
        return 0;
}


结构体和指针结合使用总结
 

//1、指针指向栈区空间
struct Student *p;
struct Student tmp;
p = &tmp;
p->age = 18;

//2、指针指向栈区空间
struct Student *p;
p = (struct Student *)malloc(sizeof(struct Student));
p->age = 18;

//3、字符指针

//a、字符指针保证字符常量首元素地址
char *p;
p = "mike"; //ok
            
//b、指向栈区空间
char *p;
char buf[100];
p = buf;
p = &buf[0];
strcpy(p,"mike");//往p所指向的内存拷贝内容
                 
//c、指向堆区空间
char *p;
p = (char *)malloc(strlen("mike")+1);
strcpy(p,"mike"); //往p所指向的内存拷贝东西
                  
struct Student
{
        int age;
        char *name;
        int score;
};      
//4、结构体嵌套一级指针
//a、指针data区
struct Stududent obj;
obj.name = "mike";

//b、指向栈区空间
struct Student obj;
char buf[100];
obj.name = buf;
strcpy(obj.name,"mike");//往p所指向的内存拷贝内容
                 
//c、指向堆区空间
struct Student obj;
obj.name = (char *)malloc(strlen("mike")+1);
strcpy(obj.name,"mike"); //往p所指向的内存拷贝东西
                         
//d、参考结构体嵌套一级指针

共用体(联合体)

#include<stdio.h>
union Test
{
        unsigned char a;
        unsigned short b;
        unsigned int c;
        //double d;
};
int main()
{
        //1、结构体的大小可以简单认为成员大小的累加
        //2、共用体的大小为最大成员的大小
        printf("%lu\n",sizeof(union Test));

        //3、共用体公有一块内存,所有成员的地址都一样
        union Test obj;
        printf("%p,%p,%p,%p\n",&obj,&obj.a,&obj.b,&obj.c);

        //4、给某个成员赋值,会影响到另外的成员
        //左边是高位,右边是低位
        //高位放高地址,低位放低
        obj.c = 0x44332211;
        printf("obj.c = %x\n",obj.c);
        printf("obj.b = %x\n",obj.b);
        printf("obj.a = %x\n",obj.a);

        obj.a = 0xaa;
        printf("obj.c = %x\n",obj.c);
        printf("obj.b = %x\n",obj.b);
        printf("obj.a = %x\n",obj.a);

        obj.b = 0xccdd;
        printf("obj.c = %x\n",obj.c);
        printf("obj.b = %x\n",obj.b);
        printf("obj.a = %x\n",obj.a);

        return 0;
}

枚举的使用

#include<stdio.h>
/*
#define pink 0
#define red 1
#define white 3
#define blue 4
#define yellow 5
*/
//enum是关键字
//里面的成员是一个标示符,枚举常量
//第一个成员如果没有赋值,默认为0,下一个成员比上一个多1
//枚举类型enum Color
//成员:枚举成员,枚举常量
enum Color
{
        pink,red,green=10,white,blue,yellow  //可以对其进行初始化
};
int main()
{
        int flag = 1;
        if(flag == red)
        {
                printf("red\n");
        }

        //枚举变量flag2
        enum Color flag2;

        //1、可以使用枚举成员给flag2赋值
        flag2 = pink; //等价于pink = 0

        //2、也可以使用常量给flag2赋值,不推荐
        flag2 = 3;

        return 0;
}

typedef的使用

#include<stdio.h>
struct Test
{
        int a;
};
//定义一个结构体变量
struct Test obj;
//给struct Test2类型起了一个别名叫Test2
typedef struct Test2
{
        int a;
}Test2;
Test2 tmp;//少了struct
int main()
{
        //1、typedef给一个以存在的类型起一个别名
        //2、typedef不能创建新类型
        typedef int int64; //有分号

        int64 a; //int a; //宏定义发生在预处理
                          //typedef是在编译阶段 
        return 0;
}

课堂笔记

const修饰的结构体变量:

struct Student
{
        int age;
        char name[50];
        int score;
};
struct Student tmp;
struct Student *p1 = &tmp;
p1->age = 18;//ok
p1 = NULL; //ok

//const修饰的是*,指针指向的内存不能修改
const struct Student *p2 = &tmp;
struct Student cosnt *p2 = &tmp;
p2->age = 18;//err
p2 = NULL;//ok

struct Student * const p2 = &tmp;
p2->age = 18; //ok
p2 = NULL; //err

相关文章:

  • linux网络设置
  • 协程的原生挂起与恢复机制
  • 【深度学习与大模型基础】第10章-期望、方差和协方差
  • 文献分享: DESSERT基于LSH的多向量检索(Part3.2.外部聚合的联合界)
  • lx2160 LSDK21.08 firmware 笔记 - 0.基于fip.bin 编译流程展开的 makefile 分析
  • DrissionPage详细教程
  • Django3 - 建站基础
  • AcWing 5969. 最大元素和
  • openapi + knife4j的使用
  • C++动态规划基础入门
  • Numpy和OpenCV库匹配查询,安装OpenCV ABI错误
  • 深度学习ResNet模型提取影响特征
  • 小米运维面试题及参考答案(80道面试题)
  • CST1016.基于Spring Boot+Vue高校竞赛管理系统
  • DOM解析XML:Java程序员的“乐高积木式“数据搭建
  • 国内AI大模型卷到什么程度了?
  • Linux虚拟内存详解
  • LLaMA 常见面试题
  • 探索加密期权波动率交易的系统化实践——动态对冲工具使用
  • 配置SecureCRT8.5的粘贴复制等快捷键
  • 人猴“攻防战”:难守的庄稼与扩张的猴群,部分村民选择放牧搬家
  • 技术派|台军首次试射“海马斯”火箭炮,如何压制这种武器?
  • 贵州茅台股东大会回应八大热点:确保茅台酒价格体系稳固,相信自我调节能力
  • 国家主席习近平任免驻外大使
  • 国际观察丨美中东政策生变,以色列面临艰难选择
  • 特写|银耳种植“北移”到沧州盐山,村民入伙可年增收4万元