文章目录

  • 内存结构
    • 作用域
      • 局部变量
      • 全局变量
      • 静态变量
        • 静态局部变量
        • 静态全局变量
      • 全局函数和静态函数
        • 静态函数
        • 全局函数
    • 内存布局
      • 内存分区
        • 代码区(程序指令)
        • 数据区(静态区、全局区)
        • 栈区
        • 堆区
        • 堆区动态分配,冒泡排序
      • 存储类型总结内存操作
        • void *memset(void *s, int c, size_t n)
        • void *memcpy(void *dest, const void *src, size_n)
        • memmove()
        • int memcmp(const void *s1, const void *s2, size_t n)
  • 复合类型
    • 结构体
      • 初步介绍
      • 结构体指针
        • 结构体里包含指针类型
        • 结构体指针
        • 结构体作为参数
        • 嵌套结构体
      • 共用体(联合体)
      • 枚举
      • typedef

内存结构

作用域

  • 代码块作用域
  • 函数作用域
  • 文件作用域

局部变量

一般在代码块内部的变量

  • 在该函数内定义,则只在该函数内部有效;
  • 在复合语句中定义,只在复合语句中有效;
    随着调用/语句的结束局部变量的声明周期也结束;
    若无赋初值,则内容随机。注意:若为赋值就将变量作为循环或其他语句判断条件的程序会出错!!!

全局变量

  • extern 数据类型 变量名; 声明一个变量,这个变量在别的文件中已经定义了,这里只是声明,不是定义。

静态变量

静态局部变量

static 局部变量的作用域也是在定义的函数内有效;
static 局部变量的生命周期和程序运行周期一样,同时 static 局部变量的值只初始化一次,但可多次赋值;
若未赋值,则系统自动赋值。int - 0char - NULL

/*使用静态*/
#include<stdio.h>int main()
{int i = 0;for (i=0; i<10; i++){static int j = 100;printf("%d\n", j -=i);}return 0;
}

/*使用静态*/
#include<stdio.h>int main()
{int i = 0;for (i=0; i<10; i++){int j = 100;        // 运行每次都初始化j,意味着每次运算j都为100printf("%d\n", j -=i);}return 0;
}

由以上俩个运行结果可验证静态变量只能初始化一次,但可赋值。

静态全局变量
  • 在函数外定义,作用范围被限制在所定义的文件中;
  • 不同文件静态全局变量阔以重名, 作用域不冲突;
  • 静态全局变量的生命周期和程序运行周期不一样,同时静态全局变量的值只初始化一次。

全局函数和静态函数

静态函数

仅限于当前文件内调用

全局函数

可使用于当前项目中

内存布局

内存分区

在程序没有加载到内存前,分为代码区(test)、数据区(data)、未初始化数据区(bss)

代码区(程序指令)
数据区(静态区、全局区)

初始化数据

  • 初始化的全局变量
  • 初始化的静态全局变量
  • 初始化的静态局部变量

未初始化数据

  • 未初始化的静态局部变量,默认未0
  • 未初始化的全局变量默认初始值为0
  • 未初始化的静态全局变量,默认未0

字符串常量

栈区
  • 变量
  • 数组
  • 结构体
  • 指针
  • 枚举
  • 函数形参

栈区大小
在不同的操作系统中系统分配给每一个程序的栈区空间大小不同:不是公用,但可被访问

  • 一般windows为1-8M
  • 一般Linux为1-16M
堆区

用于动态内存分配、与物理内存有关

  • 音频文件
  • 视频文件
  • 图像文件
  • 文本文件
  • 大的数据
堆区动态分配,冒泡排序
#include<stdio.h>
#include<time.h>
#include<stdlib.h>int main()
{int i=10, j, k;srand((unsigned int)time(NULL));   // 创建随机种子int *p = (int *)malloc(sizeof(int) * i);  # 开辟空间for (j=0; j<i; j++){p[j] = rand() % 50; }for(j=0; j<i-1; j++){for(k=0; k<i-j-1; k++){if(p[k] < p[k+1]){int temp = p[k];p[k] = p[k+1];p[k+1] = temp;}}}for(j =0; j<10; j++){printf("%5d", p[j]);}return 0;
}

存储类型总结内存操作

void *memset(void *s, int c, size_t n)
  • 作用:将s的内存区域所有字节都填入c
  • 参数:
    • s:需要操作内存s的首地址;
    • c:类型必须为unsigned char 【0-255】;
    • n:指定需要设置的大小
  • 返回值:s的首地址
void *memcpy(void *dest, const void *src, size_n)
  • 功能:拷贝src中内存中前n个字节到dest内存地址上
  • 参数:
    • dest:目的内存首地址
    • src:源内存地址首地址【dest和src内存空间不可重叠】
    • n:需要拷贝的字节数
  • 返回值:dest的首地址

memcpystrcpy()的区别:

  • 前者是以个数为准,相对广泛。
  • 后者是以\0为结尾。
memmove()

功能用法和memcpy一样。区别再与当destsrc内存空间重叠时,它阔以处理。但效率低。

int memcmp(const void *s1, const void *s2, size_t n)
  • 功能:比较s1和s2所指向内存区域的前n个字节。
  • 参数:
    • s1:s1内存首地址;
    • s2:s2内存首地址;
    • n:比较前n个字节。
  • 返回值:
    • 相等: = 0;
    • 大于:>0;
    • 小于:<0。

复合类型

结构体

初步介绍

定义

struct 结构体名称
{// 结构体成员列表
}变量名...; // 可用,分割开定义多个变量名称// 若前面为定义变量名,后续可用;
struct 结构体名称 变量名;

赋值

/*第一种*/
struct 结构体名 变量名 = {按列表顺序值};/*第二种*/
变量名.属性 = 值;
// 需要注意:若遇到字符串,则需要使用strcpy()进行拷贝;由于字符串常量是一个常量数组,可以读取,但不能修改。

内存

结构体需要根据数据类型进行对齐
【注意】:所以数据类型的大小在内存中存储的地址一定是它的类型的倍数。
如何结构体中节省内存

  • 找出结构体中数据类型最大的
  • 按照排序将每一个都填充满,若有剩余,则下一个刚才满足该空间的,即可在同一个空间,若不满足,则需要下一个空间

例如:


冒泡排序在结构体中的应用

#include<stdio.h>/***********定义结构体**********/
struct stu2{char name[15];float score;
};/***********冒泡排序**********/
void sortStruct(stu2 *s)
{for(int i=0; i<3; i++){for(int j=0; j<4-i-1; j++){if(s[j].score < s[j+1].score){stu2 temp = s[j];s[j] = s[j+1];s[j+1] = temp;}}}
}int main()
{struct stu2 s[4];       // 创建结构体// 循环写入多条数据for(int i=0; i<4; i++){printf("请输入姓名和成绩:\n");scanf("%s%f", s[i].name, &s[i].score);}// 冒泡排序sortStruct(s);// 循环取出每一条数据for(int i=0; i<4; i++){printf("请输入姓名:%s,成绩:%.2f\n", s[i].name, s[i].score);}
}

结构体指针

结构体里包含指针类型
 struct stu{char *name;float score;};

注意

在使用指针的时候,使用malloc为它开辟堆空间,节省了栈空间。在使用完成后需要对它进行释放free

结构体指针

定义

// 结构体
struct stuInfo
{char *name;int Num;
}stu_;int main()
{// 创建堆空间结构体// 创建结构体指针struct stuInfo *s = &stu_;// 申请空间s->name = (char *)malloc(sizeof(char)*15);strcpy(s->name, "虾米");s->Num = 001;printf("%s, %d", s->name, s->Num);// 释放空间free(s->name);return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>struct stuInfo2
{char *name;float *scores;
};int main()
{struct stuInfo2 *s = (struct stuInfo2 *)malloc(sizeof(struct stuInfo2)*3);for (int i=0; i<3; i++){s[i].name = (char *)malloc(sizeof(char)*15);s[i].scores = (float *)malloc(sizeof(float)*2);strcpy(s[i].name, "小米");s[i].scores[0] = 20.2;s[i].scores[1] = 22.2;}for(int i=0; i<3; i++){printf("%s, %.2f, %.2f\n", s[i].name, s[i].scores[0], s[i].scores[1]);free(s[i].name);free(s[i].scores);}//注意:先先释放内部的,在释放结构体free(s);return 0;
}

获取变量

可以通过 -> 获取指针变量

结构体作为参数

以下包含四种用法

#include<stdio.h>
#include<stdlib.h>
#include<string.h>struct stuInfo3
{char name[15];int Num;
};// *传入结构体:值传递不会改变实参的值。
void funCom(struct stuInfo3 s)
{strcpy(s.name, "小米");s.Num = 20;printf("%s, %d\n", s.name, s.Num);
}// *传入结构体指针:传递地址会改变值
void funPointer(struct stuInfo3 *s)
{strcpy(s->name, "小栏");s->Num = 90;
}// *返回结构体
struct stuInfo3 returnS()
{struct stuInfo3 s = {"里斯", 29};return s;
};// *返回结构体指针
struct stuInfo3 *returnPointerS()
{struct stuInfo3 s;strcpy(s.name, "小");s.Num = 01;return &s; // 返回地址后,前面的值在栈区被销毁
};int main()
{//struct stuInfo3 s = {"里斯", 19};//funCom(s);//funPointer(&s);//struct stuInfo3 s = returnS();struct stuInfo3 *s = returnPointerS();printf("%s, %d\n", s->name, s->Num);return 0;
}
嵌套结构体

嵌套的意思就是在结构体内部再创建一个结构体。其调用方法只需在往内层 . 一个即可

// 内层
struct inner
{int inNum;char inName[15];
};
// 外层
struct external
{int exAge;struct inner sIn;
}; int main()
{struct external s;s.exAge = 20;strcpy(s.sIn.inName, "小米");s.sIn.inNum = 2;printf("%d, %s, %d", s.exAge, s.sIn.inName, s.sIn.inNum);return 0;
}

共用体(联合体)

  • 是一个能在同一个存储空间存储不同数据类型的类型;
  • 所占的内存长度等于其最长成员的长度
  • 同一内存段可以用来存放几种不同类型的成员,但每一瞬时只有一种起作用;
  • 其变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖
  • 其变量的地址和它的各成员的地址都是同一个地址

定义

union 共用体名称 成员列表 共用体变量名

#include<stdio.h>union 共用体名称
{成员列表;
}共用体变量名;

枚举

  • 将变量的值一一都列举出来,变量的值只限于列举出来的值的范围内;
  • 枚举值是常量,不能在程序中用赋值语句再次对它赋值;
  • 举元素本身由系统定义了一个表示序号的数值从0开始顺序定义为0,1…。
#include<stdio.h>enum 枚举名
{枚举值表(枚举元素);
}

typedef

自定义数据类型新名字,发生在编译阶段

C基础 | 【05】(内存结构以及复合类型)相关推荐

  1. 黑马程序员C语言基础(第八天)复合类型(自定义类型)(结构体)、共用体(联合体)、枚举enum、 typedef

    黑马程序员C语言基础(第一天) 黑马程序员C语言基础(第二天) 黑马程序员C语言基础(第三天) 黑马程序员C语言基础(第四天)数据类型 黑马程序员C语言基础(第五天)运算符与表达式.程序流程结构.数组 ...

  2. winform point数组带数值_带你学够浪:Go语言基础系列 - 8分钟学复合类型

    对于一般的语言使用者来说 ,20% 的语言特性就能够满足 80% 的使用需求,剩下在使用中掌握.基于这一理论,Go 基础系列的文章不会刻意追求面面俱到,但该有知识点都会覆盖,目的是带你快跑赶上 Gol ...

  3. Java基础——JVM内存结构

    推荐阅读:https://www.cnblogs.com/wangjzh/p/5258254.html 一.内存结构图 先导知识: 一个 Java 源程序文件,会被编译为字节码文件(以 class 为 ...

  4. jav基础回顾-内存结构

    物理地址 堆的物理地址分配对对象是不连续的.因此性能慢些.在GC的时候也要考虑到不连续的分配,所以有各种算法.比如,标记-消除,复制,标记-压缩,分代(即新生代使用复制算法,老年代使用标记--压缩) ...

  5. 复合类型_没有学不会的python--复合类型(1)--概念和元组

    其实复合类型并不复杂,对于没有学习过python的朋友来说,完全不用担心. 复合类型是什么? 前面我们有讲述过简单数据类型,由于我在多个平台都有上传文章,所以这里就不贴出链接来了,烦请有需要的朋友自己 ...

  6. Go 存储基础 — 内存结构体怎么写入文件?

    作者 | 奇伢       责编 | 欧阳姝黎 概述 讲了那么多存储的通用知识,从 Linux 的文件系统,块层,再到磁盘,都做了一些深入的分享.今天分享一个 Go 编程的使用技巧:怎么把内存的结构体 ...

  7. [Java基础] -- Java7/8 内存结构的理解

    本文转自:https://blog.csdn.net/laomo_bible/article/details/83067810 Java内存结构是每个java程序员必须掌握理解的,这是Java的核心基 ...

  8. Oracle数据库基础入门《二》Oracle内存结构

    Oracle数据库基础入门<二>Oracle内存结构 Oracle 的内存由系统全局区(System Global Area,简称 SGA)和程序全局区(Program Global Ar ...

  9. 菱形继承,多继承,虚继承、虚表的内存结构全面剖析(逆向分析基础)

    // 声明:以下代码均在Win32_Sp3   VC6.0_DEBUG版中调试通过.. 在逆向还原代码的时候,必须得掌握了菱形继承,多继承,虚继承虚函数的内存虚表结构.所以,这篇文章献给正在学习C++ ...

最新文章

  1. Python optionParser模块的使用方法
  2. 【整理】Oracle创建/删除表空间
  3. python在线翻译代码_Python 20行简单实现有道在线翻译的详解
  4. wxWidgets:wxListView类用法
  5. Linux中使用异步 I/O 大大提高应用程序的性能
  6. 【Android】Android开发启动app弹出一张广告图片,Dialog可以查看大图,查看某个图片功能...
  7. python写数据到mysql_使用python3 实现插入数据到mysql
  8. graph面板x轴模式包括哪些_激光五轴加工机床技术参数有哪些?
  9. python实现新闻网站_Python 教你 4 行代码开发新闻网站通用爬虫
  10. 精选|2019年1月R新包推荐
  11. Redis的持久化方式
  12. 阿甘正传中的人生哲理
  13. 看过这篇文章,再也不要说你是凭实力单身了
  14. 【渝粤题库】广东开放大学 标准化专业英语 形成性考核
  15. Java面试题总结之数据结构、算法和计算机基础(刘小牛和丝音的爱情故事1)...
  16. 进程和计划任务管理|linux
  17. 《袁老师访谈录》第十九期-【在商言商·思享会】(第一场)“企业如何抓住新一代科技红利”...
  18. imputation文献-A systematic evaluation of single-cell RNA-sequencing imputation methods
  19. 如何在Office 2013或2016中带回Microsoft Office Picture Manager
  20. linux批处理模式,巧用linux-top的批处理模式

热门文章

  1. 小白看了也能搭建物联网项目——物联网开发板——QD-mini板
  2. M5stack StickCplus ESP32物联网开发板初体验
  3. EXCEL怎么隔3行插入1空行?
  4. traceroute的工作原理
  5. 097 《终结拖延症》简记
  6. 拼多多微信登陆服务器请求失败,拼多多客服网页无法登陆/卡死,怎么办?
  7. 什么是再生纤维素纤维
  8. python从文件中读数据并进行排序
  9. 如何用分词来简化状语从句
  10. python获取qq好友ip_使用Python模拟登录QQ邮箱获取QQ好友列表