重拾C语言基础知识

从实习到工作两年多的时间了,虽然感觉学到了很多知识,但是事实上却将立足之本的基础知识给忘了个精光。也许跟自己没有出去找工作有关,没有好好的将C语言的基础牢牢掌握。

从现在开始吧!好好的重温基础,做一名合格的程序猿!!!!

题目一 参数传递的值传递和其它传递

 

  1. void GetMemory( char *p)  
  2. {  
  3.     p = (char *) malloc( 100 );  
  4.     strcpy( p, "hello world" );  
  5. }  
  6.   
  7. void main(void)  
  8. {  
  9.     char *str=NULL;  
  10.     GetMemory(str);  
  11.     puts(str);  
  12. }  

这个程序是否有错?

 

从main函数开始,可以看到首先是定义了一个char类型的指针str,然后调用了GetMemory函数,此函数的参数是char 类型的指针。当函数中运行

 p = (char *) malloc( 100 ); 

的时候,是把分配的地址赋值给了P,而此时p所指向的地址和str所指向的地址并不同了。所以整个操作的过程中实际上进行的是值传递而不是地址的传递。

    那么进一步思考这个问题的话,我们可以通过地址传递和引用传递的方式进行改进程序。

题目二 编译器相关volatile

    编译器优化常用的方法有:将内存变量缓存到寄存器;调整指令顺序充分利用CPU指令流水线,常见的是重新排序读写指令。volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以消除一些代码。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化。

volatile的本意是“易变的” 因为访问寄存器要比访问内存单元快的多,所以编译器一般都会作减少存取内存的优化,但有可能会读脏数据。使用了volatile之后,每次在读取数据的时候都是从变量的地址处读取,而不是从cache中或者寄存器的备份中读取。

基于这种变量的特殊性,那么就应该合理使用,常见的应用场景:

1.中断服务程序中修改的供其它程序检测的变量需要加volatile

2.多任务环境下各任务间共享的标志应该加volatile

3.存储器映射的硬件寄存器通常也要加voliate,因为每次对它的读写都可能有不同意义

另:linux kernel中的内存屏障https://www.kernel.org/doc/Documentation/memory-barriers.txt

题目三 C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)

 

BSS段:(bss segment)通常是指用来存放程序中未初始化全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

 

数据段 :数据段(data segment)通常是指用来存放程序中 已初始化  全局变量 的一块内存区域。数据段属于静态内存分配。 
代码段: 代码段(code segment/text segment)通常是指用来存放 程序执行代码 的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于 只读 , 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些 只读的常数变量 ,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.
堆(heap) :堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)。堆(heap),堆一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
栈(stack) :栈又称堆栈, 存放程序的 局部变量 (但不包括static声明的变量, static 意味着 在数据段中  存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场储动态内存分配,需要程序员手工分配,手工释放

下图是一个典型C内存空间分布图

题目四 ARM体系中所描述的RO,RW和ZI
一个ARM程序包含3部分:RO,RW和ZI
  • RO是程序中的指令和常量
  • RW是程序中的已初始化变量
  • ZI是程序中的未初始化的变量
由以上3点说明可以理解为:
  • RO就是readonly,
  • RW就是read/write,
  • ZI就是zero
ARM映像文件的组成
所谓ARM映像文件就是指烧录到ROM中的bin文件,也成为image文件。以下用Image文件来称呼它。
Image文件包含了RO和RW数据。
之所以Image文件不包含ZI数据,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。

 

posted on 2013-10-30 22:30  you Richer  阅读(218)  评论(0编辑  收藏  举报