C语言高级-C内核

本博客参考《嵌入式Linux与物联网软件开发C语言内核深度解析》

一. C 语言与内存

对于单片机而言,C语言程序

                                                内存是用来存储可变数据(变量)的,

                                                常量存储在 flash 当中。

1. 对于内存:

        无操作系统:通过编译器提供的

                变量名来管理内存(编译器会将变量名与给其分配的内存首字节地址绑定),

                函数名(指针)本质也是一个内存地址,

                定义数组就是一次性定义一堆变量(第一个变量a[0]的地址记录在数组名a中),

                结构体为聚合数据类型,一般传递结构体变量的指针来操作结构体。

        有操作系统:

                静态内存分配,

                动态内存分配:使用 API,例如 malloc、free 接口

        C++:new 对象分配内存,delete 删除对象

        Java/C#:虚拟机

        分类:静态内存 SRAM,动态内存 DRAM

        特点:可以随机访问

三总线:地址总线、数据总线、控制总线(地址总线位数决定内存的大小 2^N 次方)

        1 GB = 1024 MB  1 MB = 1024 KB  1 KB = 1024 B  1 B ( 字节 ) = 8 bit ( 位 )

        内存编址以字节为单位

        数据类型的本质是一个内存格子(存放数据值)的长度解析方法

2. 栈 stack

        作用:用来保存非静态局部变量,将局部变量放入栈中(入栈),释放局部变量(出栈)(两操作由背后的运行时系统自动完成),在程序运行过程中跳转函数要通过栈来保存和恢复现场。

        特点:小内存、自动化;先进后出;栈的大小可以设定的。

3. 堆 heap

        作用:需要的内存容量比较大时,动态申请存储大容量数据,比如链表

        特点:大内存、手工分配/使用/释放。

4. 静态存储区

        作用:存放静态局部变量全局变量

        特点:随程序运行而分配空间,直到程序运行结束才释放释放空间。

二. C 语言位操作

1. c 语言位操作:

        位与 & :逐位相与

        位或 | :逐位相或

        位异或 ^ :不同为 1 ,相同为 0 。

        位取反 ~ :按位取反。

        左移位 << :左边移出,右边补零,x << n =x * 2^n

        右移位 >> :右边移出,左边补零,x >> n = x / 2^n

2. 寄存器操作:

        REG1 中的值为 0x AAA AAA AAA

        特定位( 8 ~ 15 )清零用 & :

REG1 & = 0xFFFF00FF;
REG1 & = ~ 0x0000FF00;

        特定位( 8 ~ 15 )置 1 用 | :

REG1 |= 0x0000FF00;

        特定位( 8 ~ 15 )取反用 ^ :

REG1 ^= 0x0000FF00;

3. 位运算构建特定的数:

        左移 << + 或 |

        左移 << + 或 | + 取反 ~

4. 宏定义完成位运算:

        置位:

#define SET_BIT_N(x,n) ((x) | (1 << ((n)-1)))

        复位:

#define CLR_BIT_N(x,n) ((x) & ~(1 << ((n)-1)))

        截取变量连续的部分:

#define GETBITS(x,n,m) ( (x & ~ (~(0U) << (m-n+1) ) << (n-1)) >> (n-1) )

三. 指针才是 C 语言的精髓

1. 指针定义

int a = 10;

int *p = &a;        //将 a 的地址给指针 p,指针指向 a 变量。

*p = 20;        //取指针 p 的值,并将其赋为 20,对应的 a  的值也被改为 20。

* 有两个作用,一是表示指针的级数,二是解引用(即取空间操作)。

& 为取地址符。

对于变量,左值一般是对应的写操作,右值对应读操作。

2. 野指针的产生原因:

        1. 指针不是一个有效的地址。

        2. 没有访问权限,对于字符串常量,只允许读操作,不允许写操作。

        3. 内存越界。

防止野指针:要常将指针赋为 NULL,NULL 在 C++ 中为 0,在 C 语言里为 (void *) 0 ,为空指针。

3. const 修饰:

        1. int const *p :指针 p 所指向的空间是常量,不能被修改,但 p 是可以被修改的。

        2. int *const p :指针 p 所指向的空间是可以修改的,p 是不可以被修改的。

        3. int const *const p :什么都不能修改。

对于 const 变量,可以通过指针的引用修改其值。

所谓的常量其实是防止常量区 .ro.data 里的用 const 进行修饰的变量。

4. 对于数组:

        1. 数组名就是数组的首地址,它同样等于数组 0 取地址,即 buf = & buf[0]。

        2. &buf 取到的还是数组的首地址,不过是首地址值,地址 +1,加的是地址值本身的数值加一。

        3. 使用指针访问数组:

                1. 利用下标访问。

                2. 利用指针常量访问。

                3. 利用指针变量访问,地址 +1,加的是一个数组元素空间的大小。

5. 强制类型转换

对于不同类型的数据,存储结构和方式,以及存储的空间大小会有所不同。

强制类型转换会:

        1. 导致空间大小改变。

        2. 导致数据的存储结构改变。

        3. 对于指针,强制类型转换改变的是对空间的引用方式,一般是将引用的空间缩小,防止内存越位。

6. 数据的读写:

        1. 根据变量名或直接利用地址,找到空间首地址。

        2. 根据类型指定的空间的大小,从首字节地址开始,找出向后顺延后的空间的大小。

        3. 按照类型数据存储格式的要求,进行数据的读写。

7. sizeof 与 strlen :

 strlen和sizeof的区别是什么?不止是含义不一样,用法也不同

char str[]="hello";

sizeof(str) 结果为 6,包含 '\0' 字符

strlen(str)  结果为 5,去除了对 '\0' 的计算

char *p=str;

sizeof(*p) 结果为 1,*p 为 str[0] 的空间,大小为 1

strlen(*p) 结果为 5,计算 "hello" 的字符个数

int b[100];

sizeof(b) 结果为 400,计算数组空间

8. #define 与 typedef 

        #define 只进行简单的宏替换,预编译时被处理,可以实现类型组合,不可以构建新类型

        typedef 可以给类型起别名,是编译时被处理,不可以实现类型组合,可以构建新类型

#include <stdio.h>

typedef unsigned char u8;
typedef char ch;
#define CH char
#define U8 unsigned char

//unsigned ch a = 100;
u8 a=255;
ch b = -128; 
U8 c = 255;
CH d = -128;
unsigned CH e = 255;
int main()
{
	printf("hello,a=%d,b=%d,c=%d,d=%d,e=%d\n",a,b,c,d,e);
}

9. 传参:

        1. 普通传参:传入形参、传入指针

        2. 传递数组:传入数组首字节地址,可用一维指针代替,但这样不直观

        3. 传递结构体:成员值传递,成员地址传递,成员结构体传递,结构体地址传递

        可以使用 const 来修饰传入的指针参数不可被修改

四. C 语言复杂表达式与指针高级应用

1. 指针数组

        概念:放指针的数组

        int *p[5] 为大小为 5 的 int * 类型的数组

2. 数组指针

        概念:指向数组的指针

        int (*p)[10] 为指向大小为 10 的 *p

3. 函数指针

        概念:指向函数的指针

        int (*pFunc)(int,int) 为指向返回值为 int 的含有两个 int 形参的函数

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值