• C理解(一):内存与位操作


    本文主要探讨C语言的内存和为操作操作相关知识。

    冯诺依曼结构和哈佛结构
            冯诺依曼结构:数据和代码放在一起,便于读取和修改,安全性低
            哈佛结构是:数据和代码分开存放,安全性高,读取和修麻烦

    内存
            内存是用来存储全局变量、局部变量等变量
            操作系统把内存分成4kb页面以为单位来管理

            页面内以字节为单位通过管理接口(API)管理内存

    内存属性
            内存属性:地址和空间
            空间:内存单元大小
            地址:内存条上的实际位置(物理地址)和逻辑地址(地址编号)一一对应
            内存单元类似方格,方格的位置为物理地址,方格的编号为逻辑地址,方格的空间为内存单元空间大小

    内存和数据类型
            int类型与CPU数据位宽相同,32位的CPU的位宽是32位,int类型为32位,占4字节
            数据类型表示内存单元长度和解析方式
            int读取过程中,从起始处读取4个字节单元,再int的方式解析读取的内容

    内存对齐
            内存对其访问效率高
            int类型变量对齐与非对齐
                对齐:    0 1 2 3    
                非对齐: 1 2 3 4    

    变量访问内存
            int a;编译器申请int类型内存内存单元,把a和内存单元绑定
            a = 5;内存单元空间中写入5
            a += 4; 编译器先读a值再加4,最后重写写入到内存单元。


    指针间接访问内存
            int a;int *p;
            a和p代表内存地址,内存地址长度和解析方法不同
            a为int型,长度是4字节,解析方式是int
            p是int *类型,长度是4字节,解析方法是int *

    数组访问内存
            int b[10];
            编译器分配40个字节长度给b,首元素地址和b绑定
            每个元素类型都是int,长度是4字节
            第一个字节地址为首地址,首元素a[0]地址为首地址

    栈(stack)
            自动分配和回收内存
            内存空间可反复使用
            内存使用完不会清理,使用前需初始化
            操作系统固定了栈大小,变量定义防止栈溢出
            栈变量指针空间是临时的,同一变量每次初始化使用的是不同的内存地址空间
      
    堆(heap)
            堆管理内存分配灵活,按需分配
            内存按需申请使用,使用完释放
            内存空间可反复使用
            内存使用完不会清理,使用前需初始化

    内存申请
                    void *malloc(size_t size);
                    void *calloc(size_t nmemb, size_t size);  // nmemb个单元,每个单元size字节
                    void *realloc(void *ptr, size_t size);    // 改变原来申请的空间的大小的
                    malloc用来申请内存,返回void *类型指针,malloc返回申请内存空间首地址,失败返回NULL
                    malloc只分配内存空间,空间存储的数据类型不做定义

            代码段:程序中可执行部分
            数据段(数据区、静态数据区、静态区):初始化为非零的全局变量,静态局部变量
            bss段(ZI段):初始化为0或未初始化的全局变量

    特殊数据
            char *p = "linux";字符串分配在代码段,是常量不是变量
            单片机编译过程中将const修饰变量放在代码段实现不能修改
            gcc编译器将const修饰的变量放在数据段,只是默认不可修改,实际可通过地址访问修改

    (32位操作系统)
            位(1bit) 
            字节(8bit) 
            半字(16bit)  
            字(32bit)

    位操作
            位操作:与& 或| 取反~ 异或^ 左移<< 右移>>
            位清0 : & 0
            位置1 : | 1
            位取反 : ^ 1
            特定位设置
                    #define SET_NTH_BIT(x, n)  (x | ((1U)<<(n-1)))
            特定位清除
                    #define CLEAR_NTH_BIT(x, n) (x & ~((1U)<<(n-1)))
            截取特定位
                    #define GETBITS(x, n, m) ((x & ~(~(0U)<<(m-n+1))<<(n-1)) >> (n-1))

    demo:
            位清除,设置,截取练习

    1. #include <stdio.h>
    2. int main()
    3. {
    4. int a = 0x8a66;
    5. //设置bit3
    6. a |= (1<<3);
    7. printf("bit3 set :%x\n",a);
    8. //设置bit3 ~ bit8
    9. a |= (0x1f << 3);
    10. printf("bit3-8 set :%x\n",a);
    11. //清除bit5
    12. a &= ~(1 << 5);
    13. printf("bit5 clear :%x\n",a);
    14. //清除bit6 ~ bit12
    15. a &= ~(0x3f << 6);
    16. printf("bit6-12 clear :%x\n",a);
    17. //设置bit9 ~ bit149
    18. a &= ~(0x1f << 9);
    19. a |= (12 << 9);
    20. printf("set 12 in bit9-14 :%x\n",a);
    21. //bit6 ~ bit129,bit4 ~ bit77
    22. int tmp = ((a & (0x3f << 6)) >> 6) + 9;
    23. a = (a & ~(0x3f << 6)) | (tmp << 6);
    24. tmp = ((a & (0xf << 1)) >> 1 ) + 7;
    25. a = (a & ~(0xf << 1)) | (tmp << 1);
    26. printf("bit6-12 + 9 and bit1-4 +7 :%x\n",a);
    27. return 0;
    28. }

    结果示例:

  • 相关阅读:
    Springboot毕设项目博恒人力资源规划系统671c9(java+VUE+Mybatis+Maven+Mysql)
    智慧公厕擦手纸洗手液余量实时在线统计
    提问为什么hive中ads层建表一直出错
    Kotlin协程:Flow的融合、Channel容量、溢出策略
    测温仪的原理是什么?
    opencv-python图像处理:Canny边缘检测算法,模板匹配,直方图均衡化,傅里叶变换
    vscode打开settings.json方法
    C++中的命令模式
    练习作业改错
    基于C++实现的状态空间的启发式搜索
  • 原文地址:https://blog.csdn.net/tyro_wzp/article/details/133410965