C语言高级部分总结

摘要:
C语言的高级部分总结了嵌入式ARM3的信息来自网络1。内存主题1.0。内存是程序的立足点,但用户可以通过除以8将其转换为字节。内存存储为int。调用函数后,它将自动编译为一个汇代码,以立即更改堆栈顶部。变量将自动放置在堆栈(堆叠)上。调用函数后,堆内存仅在malloc和free之间属于我的进程。

C语言高级部分总结

嵌入式ARM 3天前

信息来源于网络

一、内存大话题

1.0、内存就是程序的立足之地,体现内存重要性。

1.1、内存理解:

内存物理看是有很多个Bank(就是行列阵式的存储芯片),每一个Bank的列就是位宽 ,每一行就是Words,则存储单元数量=行数(words)×列数(位宽)×Bank的数量;通常也用M×W的方式来表示芯片的容量(或者说是芯片的规格/组织结构)。

M是以位宽为单位的总容量,单位是兆 ,W代表位宽, 单位是bit。计算出来的芯片容量也是以bit为单位,但用户可以采用除以8的方法换算为字节(Byte)。比如8M×8,这是一个8bit位宽芯片,有8M个存储单元,总容量是64Mbit(8MB)。

1.2、c语言中其实没有bool类型:以0表示假,非0表示真,则在内存存储是以int型存放的。如果想要表示真假,可以用int/char型做替换,在c++中就有bool x=true/false;

1.3、内存对齐:内存对齐(提高访问效率速度,编译器一般默认是4字节对齐)

1.4、char/int/short/long/float/double型:放在内存的长度和解析作用。(int *)0,使0地址指向一个int型。又比如0000111010101可以解析成int型也可以解析成float型。

1.5、Linux内核是面向对象的,而c语言是面向过程的,但可以用结构体内嵌指针变成面向对象。如

struct student{
int age; //变量
int lenth; //将相当于一个类,有变量有函数
char *name;
void (*eat)(void); //函数指针
}

1.6、栈的理解:

(1) 运行时自动分配&自动回收:栈是自动管理的,程序员不需要手工干预。方便简单。(表现在汇编代码,编译时,会自动编译成汇编码实现函数调用完立即改变栈顶)

(2) 反复使用:栈内存在程序中其实就是那一块空间,程序反复使用这一块空间。(硬件上有个寄存器,用来存放栈的栈顶地址,栈是有大小的空间)

(3) 脏内存:栈内存由于反复使用,每次使用后程序不会去清理,因此分配到时保留原来的值。

(4) 临时性:(函数不能返回栈变量的指针,因为这个空间是临时的)

(5) 栈会溢出:因为操作系统事先给定了栈的大小,如果在函数中无穷尽的分配栈内存总能用完。栈的操作(怎么出栈怎么入栈)是由具体硬件来干预,程序员只要明白原理就可以了,但是要给相应的栈寄存器赋值。当调用函数时,变量会自动放在栈中(入栈)当函数调用完后,栈会自动出栈.

( 6 ) 栈的 "发展"有四种情况,满增栈,满减栈,空增栈,空减栈,至于是那种要根据编译器决定,而s5pv21 是满减栈。

1.7、堆的理解:

(1)操作系统堆管理器管理:堆管理器是操作系统的一个模块,堆管理内存分配灵活,按需分配。

(2)大块内存:堆内存管理者总量很大的操作系统内存块,各进程可以按需申请使用,使用完释放。

(3)脏内存:堆内存也是反复使用的,而且使用者用完释放前不会清除,因此也是脏的。

(4)临时性:堆内存只在malloc和free之间属于我这个进程,而可以访问。在malloc之前和free之后都不能再访问,否则会有不可预料的后果。

(5)程序手动申请&释放:手工意思是需要写代码去申请malloc和释放free。(记住:不要把申请的地址给搞丢了, 不然自己用不了,也释放不了)

申请一段内存,可以是:
malloc(10*sizeof ( int ) );

原型:
void *malloc(size_t size);

//指针函数 size_t是宏定义int 都是便于可移植性 ,返回一个内存地址,void *可以看出,希望申请的内存用来存放什么就强制类型什么。

calloc( 10,sizeof ( int ) ); 原型:void *calloc(size_t nmemb, size_t size);// nmemb个单元,每个单元size字节void *realloc(void ptr, size_t size);// 改变原来申请的空间的大小的ptr是原来申请内存的指针,size是想要重新申请内存的大小使用就是(p+1)=12 ; *(P+3)=110;

申请失败返回NULL,申请成功返回一个地址,申请之后一定要检验(NULL!=p)用完一定要 free ( p ) ;释放后不是不能用,是不应该使用了。可以给它“洗盘子‘,p=NULL;

其实申请的内存并不能真正改变大小,原理是先重新申请一段内存,然后把原来申请的内存上的内容复制到新的内存上,然后释放掉原来的内存,返回新的指针。

(6) 在申请内存时,malloc(0)其实也是成功的,因为系统规定少于一定数目的大小,都申请规定的大小,如在win32系统下申请少于32字节的地址,最后申请到的空间是32字节,在朱老师视频中申请少于16字节的地址,最后申请到的是16字节,至于规定多少字节,由具体的系统而言。

1.8、内存里的数据:

(1)代码段:存放代码二进制、常量(char *p="linux",则”linux“存放在代码段,是不可更改的)

(2) 数据段: 存放非0全局变量、静态局部变量(局部只属于函数的,不是整个程序的)

(3) bss : 存放为0的全局变量/为0的静态局部变量、存放未初始化全局变量/静态局部变量

注意:const int a=9; 有两种存放方式:第一种确实存放在代码段,让a不能修改,第二种是仍然存放在数据段中,让编译器来判断,如果有改变的代码就会报错。 至于那种,是不确定的,像单片机就属于第一种。

1.9、《1》一个源文件实际上是以段为单位编译成连接成可执行文件(a .out );这个可执行文件总的说是分为数据段,代码段,自定义段,数据段还可以细分成 .bbs 段。而杂段会在执行的时候拿掉。所以a.out分为杂段,数据段(存放的是非0全局变量).bbs段,代码段。

《2》内存实际上被划分了两大区域,一个是系统区域,另一个是用户区域,而每一个区域又被划分成了几个小区域,有堆,栈,代码区,.bbs区,数据区(存放的是非0全局变量)。

《3》对于有操作系统而言, 当我们在执行a.out可执行文件时,执行这个文件的那套程序会帮我们把杂段清掉,然后把相应的段加载到内存对应的段。对于裸机程序而言,我们是使用一套工具将a.elf的可执行程序给清掉了所有段的符号信息,把纯净的二进制做成.bin格式的烧录文件。所以我们加载到内存的程序是连续的,也就是说代码段和数据段、.bbs段都是连续的。当然,栈空间是我们自己设置的。而且在裸机中我们不能使用malloc函数,因为我们使用的只是编译器、连接器工具没有集成库函数,没有定义堆空间区。

《4》大总结多程序运行情况: 在Linux系统中运行cdw1.out时,运行这个文件的那套程序会帮我们把相应的段加载到内存对应的段。然后操作系统会把下载到内存的具体物理地址与每条命令(32位)的链接地址映射到TTB中(一段内存空间),当我们又运行cdw2.out时,同样也像cdw1.out一样加载进去,并映射到TTB表中。而且这两个.out文件默认都是链接0地址(逻辑),当cpu发出一个虚拟地址(Linux中程序逻辑地址)通过TTB查找的物理地址是不一样的。所以对于每一个程序而言,它独占4G的内存空间,看不到其他程序。

二、位操作

2.1 ~(0u)是全1;

2.2 位与& 位或 | 位取反~ 位异或^

2.3、位与、位或、位异或的特点总结:

位与:(任何数,其实就是1或者0)与1位与无变化,与0位与变成0
位或:(任何数,其实就是1或者0)与1位或变成1,与0位或无变化
位异或:(任何数,其实就是1或者0)与1位异或会取反,与0位异或无变化

2.4、左移位<< 与右移位>> C语言的移位要取决于数据类型。
对于无符号数,左移时右侧补0(相当于逻辑移位)
对于无符号数,右移时左侧补0(相当于逻辑移位)
对于有符号数,左移时右侧补0(叫算术移位,相当于逻辑移位)
对于有符号数,右移时左侧补符号位(如果正数就补0,负数就补1,叫算术移位)

2.5、小记:常与 1 拿来 做位运算。让他取反、移位 得到想要的数。

2.6、直接用宏来置位、复位(最右边为第1位)。 置位置1,复位置0 ;

define SET_NTH_BIT(x, n) (x | ((1U)<<(n-1))) define CLEAR_NTH_BIT(x, n) (x & ~((1U)<<(n-1)))

}

三、指针—精髓

3.1 printf("%p "); 其中%p表示输出一个指针,就是指针变量(其存放的那个地址),可以理解为输出一个地址。

3.2 int* p1, p2 ; 等同于 int *p1; int p2;  int *p="Linux",其不能改变*P,因为”linux"是一个常数。

3.3 ( 代码规范性 )在定义指针时,同时赋值为NULL,在用指针时,先判断它是不是NULL。尤其是在malloc申请内存后,free(p);则一定要让p=NULL

3.4 C/C++中对NULL的理解: { #ifdef _cplusplus// 定义这个符号就表示当前是C++环境

define NULL 0;// 在C++中NULL就是0 else define NULL (void *) 0;// 在C中NULL是强制类型转换为void *的0 endif

3.5、修饰词:const (修饰变量为常量,应该理解为不应该去变它,当作常量,而并非永远不能改变,当然要看具体运行环境,在gcc,const 这种就可以采用指针方式修改,但是在在VC6.6++中就不可以修改):其虽然是当作常数,但是仍然存放在数据段中,用指针仍然可以改变值。

第一种:const int *p;
第二种:int const *p;
第三种:int * const p;
第四种:const int * const p;

3.6、 数组 int a[2]; 其中a是指首元素的首地址,&a是整个数组的收地址(数组指针,其这个指针指向一个数组),他们的值是一样的,但意义不一样,可以参照 int a; int *p=&a; 来理解。数组和指针天生姻缘在于数组名;

int a[3]; int* p=a;是可以的,但是 int p=&a;就会报错,尽管他们的值是一样的,但意义不一样,所以是不允许的,除非强制类型转换。在访问时是a[0],其实编译器会把它变成(a+0)的方式,只是用a[0]看起来更方便,封装了一下而已,实质还是指针。

3.7、 siziof()是一个运算符,测试所占内存空间,如 int a[100] ;sizeof(a)=400;

与strlen( )要有所区别,他是测字符串实际长度的,不包括‘

免责声明:内容来源于网络,仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇关联规则挖掘理论和算法《第一行代码》书籍阅读笔记下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

关于malloc和sizeof的用法

问题1: 1.L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));2.newbase = (ElemType *)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType)); 其中L是已经定义的线性表,LIST_INIT_SIZ...

微信小程序实质是什么? Hybrid App

  微信小程序是一种不需要下载安装即可使用的应用,用户扫一扫或者搜一下即可打开应用。微信小程序实质是Hybrid技术的应用。Hybrid App(混合模式移动应用)。 小程序能够更多的可以更多的调用手机本身的功能(如位置信息,摄像头等)。 主要技术:WXML(HTML5)、WXSS(CSS)、JavaScript;开发思路:使用app开发的数据绑定渲染的思...

core dumped问题查找以及使用gdb、QT下gdbserver使用

一,什么是coredump         我们经常听到大家说到程序core掉了,需要定位解决,这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止,并且在满足一定条件下(这里为什么说需要满足一定的条件呢?下面会分析)会产生一个叫做core的文件。         通常情况下,core文件会包含了程序运行时的内存,寄存器状态,堆...

(转)简单的RPC java实现 .

转;http://blog.csdn.net/jackliang55/article/details/7580563  我也承认,RPC的名声大噪之时是在2003年,那一个“冲击波”病毒(Blaster Worm virus)袭卷全球的一年。而“冲击波”正是用着RPC这把刀来敲开了远程电脑的大门。当然RPC 有更多正面的应用,比如NFS、Web Serv...

更全面的寻找post地址

我们在今后的爬虫学习过程中,要爬许许多多的网站。 唯有掌握如何对不同网站寻找到正确的post地址,才是任务之重。 比如,我访问了一个别的网站,这儿用人人网做例子。 在人人网登陆界面,使用F12进入开发者模式,找到整个登陆界面的源码: 所以,我们可以看到关键的登录模块源码有一个关键的参数,这个参数是action,存储登陆的url地址。 action="ht...

Delphi程序的自我修改

前言:     对于Delphi在编译时对代码所做的工作,大部分使用Object Pascal之类的高级语言的程序员并不是很熟悉。如果你对汇编程序以及EXE文件格式有一点基本认识,那么源代码里包含的注释将把一切解释得非常清楚。另外,我还要说明一下源代码在编译时被做了什么处理。     我对汇编程序以及EXE文件格式的认识也是及其有限的,大部分是我在寻找反盗...