C笔记
IT_FAVORITE
这个作者很懒,什么都没留下…
展开
-
笔记1:C语言变量与常量
一.变量1.1普通局部变量和全局变量的对比1.定义同时没有初始化,则局部变量的值是随机的,而全局变量的值是默认为0的。 2.使用范围上:全局变量具有文件作用域,而局部变量只有代码块作用域。 3.生命周期上:全局变量是在程序开始之前的初始化阶段就诞生的,到整个程序结束退出的时候才死亡;而局部变量在进入局部变量所在的代码块时诞生,在该代码块退出的时候死亡。 4.变量分配位置:全局变量分配在数据段上原创 2017-12-03 16:06:11 · 270 阅读 · 0 评论 -
笔记12:Linux下的文件映射区和内核映射区
一. 文件映射区文件映射区就是进程打开了文件后,将这个文件的内容从硬盘读到进程的文件映射区,以后就直接在内存中操作这个文件,读写完了后在保存时再将内存中的文件写到硬盘中去。二. 内核映射区(上图)(1)内核映射区就是将操作系统内核程序映射到这个区域了。 (2)对于linux中的每一个进程来说,它都以为整个系统只有它自己和内核而已。它认为内存地址0xC0000000以下都是它自己的活动原创 2018-01-09 19:46:00 · 1935 阅读 · 0 评论 -
笔记11:创建函数库(静态和动态)
注意:库函数不需要main函数一.创建静态库文件1.自己制作静态链接库 首先使用gcc -c只编译不链接,生成.o文件;然后使用ar工具进行打包成.a归档文件 举例: Makefile中添加 all: gcc aston.c -o aston.o ar -rc libaston.a aston.o 库名不能随便乱起,一般是lib+库名称,后缀名是.原创 2018-01-09 19:39:34 · 248 阅读 · 0 评论 -
笔记10:函数库介绍
一.函数库1.什么是函数库 1.1 函数库就是一些事先写好的函数的集合。 1.2 函数是模块化的,因此可以被复用。我们写好了一个函数,可以被反复使用。也可以A写好一个函数然后共享出来,当B有相同的需求时就不需要自己写直接用A写好的这个函数即可。二.函数库的由来1.最开始是没有函数库,每个人写程序都要从零开始自己写。时间长了慢慢的早期的程序员积累下来了一些有用的函数。 2.早期原创 2018-01-09 19:17:36 · 1959 阅读 · 1 评论 -
笔记9:递归函数
一.什么是递归函数1.1 递归函数就是函数中调用了自己本身这个函数的函数 1.2 递归函数和循环的区别。递归不等于循环 1.3 递归函数解决问题的典型就是:求阶乘、求斐波那契数列二.函数递归调用的原理2.1 实际上递归函数是在栈内存上递归执行的,每次递归执行一次就需要耗费一些栈内存。 2.2 栈内存的大小是限制递归深度的重要因素三.使用递归函数的原则:收敛性、栈溢出原创 2018-01-09 19:15:08 · 303 阅读 · 0 评论 -
笔记16:内核链表的设计思路
一.内核链表的设计思路(1)内核链表中自己实现了一个纯链表(纯链表就是没有数据区域,只有前后制作)的封装以及纯链表的各种操作函数(节点创建/插入/删除/遍历…)。 这个纯链表本身自己没有任何用处,它的用法是给我们具体链表作为核心来调用。(2)list.h文件简介 内核中核心纯链表的实现在include/linux/list.h文件中 list.h中就是一个纯链表的完整封装,包含节点定原创 2018-01-22 21:15:09 · 258 阅读 · 0 评论 -
笔记15:C语言链接属性
一.C语言程序的组织架构:多个C文件 + 多个h文件1.庞大、完整的一个C语言程序由多个c文件和多个h文件组成的。 2.程序的生成过程就是:编译 + 链接。编译是为了将函数、变量等编程.o二进制的机器码格式,链接是为了将各个独立分开的二进制的函数链接起来形成一个整体的二进制可执行程序。二.编译以文件为单位、链接以工程为单位1.编译器工作时是将所有源文件依次读进来,单个为单位进行编原创 2018-01-22 21:08:39 · 259 阅读 · 0 评论 -
笔记14:C语言中的NULL
C语言中的NULL一.NULL不是C语言关键字,本质上是一个宏定义二.NULL的标准定义:#ifdef _cplusplus#define NULL 0#else#define NULL (void *)0 //对应C语言情况#endif解释:C++的编译环境中,编译器预先定义了一个宏_cplusplus,程序中可以用条件编译来判断当前的编译环境是C++的还是C的原创 2018-01-22 20:57:17 · 873 阅读 · 0 评论 -
笔记7:结构体内存对齐
结构体中,用指针偏移量访问结构体元素时。因为结构体要考虑元素的对齐访问,所以每个元素实际占的字节数和自己本身的类型所占的字节数不一定完全一样(譬如char c实际占字节数可能是1,也可能是2,也可能是3…)一般来说,我们用.的方式来访问结构体元素时,我们是不用考虑结构体的元素对齐的。因为编译器会帮我们处理这个细节。但是C语言本身是很底层的语言,而且做嵌入式开发经常需要从内存角度,以指针的方式来原创 2018-01-03 20:16:59 · 207 阅读 · 0 评论 -
笔记8:offsetof宏和container_of宏
###一.offsetof宏做个引子: 用指针访问结构体成员 TYPE是结构体类型,MEMBER是结构体中一个元素的元素名 这个宏返回的是member元素相对于整个结构体变量的首地址的偏移量,类型是int#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER) 1.offsetof宏的作用是:用宏来计算结构体中原创 2018-01-03 20:23:44 · 306 阅读 · 1 评论 -
笔记6:字符数组和字符串的本质差异(内存分配角度)
字符数组和字符串的本质差异(内存分配角度)1.字符数组char a[] = “linux”; 定义一个数组a,数组a占6字节,右值”linux”本身只存在于编译器中,编译器将它用来初始化字符数组a后丢掉(也就是说内存中是没有”linux”这个字符串的);这句话就相当于是:char a[] = {‘l’,’i’,’n’,’u’,’x’,’\0’};2.字符串char *p = “linux”; 定原创 2018-01-03 20:11:21 · 457 阅读 · 1 评论 -
笔记5:程序中获取内存的方法
程序中获取内存的方法内存分配:栈,堆,数据段一.栈内存:反复使用:栈内存在程序中其实就是那一块空间,程序反复使用这一块空间。临时性:函数不能返回函数局部变量的地址,因为函数执行完返回后这个局部变量已经不在了 这个局部变量是分配在栈上的,虽然不在了但是栈内存还在还可以访问,但是访问实际上这个内存地址已经和当时那个变量无关了。二.堆内存:操作系统堆管理器管理;堆管理器是操作系统的一个模块,堆管理内存分原创 2018-01-03 20:08:43 · 336 阅读 · 0 评论 -
笔记4:指针和数组、函数结合分析
一.指针数组和数组指针分析指针数组和数组指针的表达式int *p[5]; int (*p)[5]; int *(p[5]);总结:我们在定义一个符号时,关键在于:首先要搞清楚你定义的符号是谁(第一步:找核心);其次再来看谁跟核心最近、谁跟核心结合(第二步:找结合);以后继续向外扩展(第三步:继续向外结合直到整个符号完)。 例如:核心是指针,就表示该结合是什么什么的指针。如果核心和*结合,表原创 2018-01-03 20:02:46 · 198 阅读 · 0 评论 -
笔记3:指针和使用时一些注意事项
一.左值和右值赋值号左边的叫左值,右边的叫右值 当一个变量做左值时,编译器认为这个变量符号的真是含义是这个变量所对应的那个内存空间;当一个变量做右值时,编译器认为这个变量符号的真实含义是这个变量的值,也就是这个变量对应的内存空间中存储的那个数。int a = 3, b =5; a = b; //当a做左值时,我们关心的是a所对应的内存空间,而不是其中存储的3 b = a; //当a做右值时原创 2018-01-01 19:45:50 · 312 阅读 · 0 评论 -
笔记2:位操作实例解析
嵌入式系统中研究的移位操作都是无符号的。 ARM是内存与IO统一编址的,ARM中有很多内部外设,SoC中CPU通过向这些内部外设的寄存器写入一些特定的值来操控这个内部外设,进而操控硬件动作。所以说,读写寄存器就是操控硬件。寄存器的特点是按位进行定义,但是寄存器的读写却是整体32位一起进行的(也就是说你只想修改bit5~bit7是不行的,必须整体32位bit一起写入)寄存器操作的要求就是,在设定特定原创 2018-01-01 19:20:51 · 265 阅读 · 0 评论 -
笔记13:存储类型关键字volatile
(1)volatile的字面意思:可变的。C语言中volatile用来修饰一个变量,表示这个变量可以被编译器之外的东西改变。编译器之内的意思是变量的值的改变是代码的作用,编译器之外的改变就是这个改变不是代码造成的,或者不是当前代码造成的,编译器在编译当前代码时无法预知。譬如在中断处理程序isr中改变了这个变量的,譬如多线程中在别的线程中更改了这个变量的值,譬如硬件自动更改了这个变量的值(一般这个变原创 2018-01-09 20:11:43 · 285 阅读 · 0 评论