随笔-1  评论-0  文章-6  trackbacks-0
  2009年12月8日

一、

1、关于字节顺序:话说在特定的硬件平台上,多字节数据的顺序存放有两种方式(little-endian、big-endian)。前者的数据的低字节

     部分存放在低地址内存,后者恰好相反。PC一般是基于IA-32微处理器,属于little-endian。某些RISC架构的CPU,例如SPARC、

    POWERPC等,则属于big-endian。

2、调用函数、栈,变量的可见范围与生命期:我们知道一个程序由数据和代码两大部分构成,而数据有几种类别,一种是“静态”的,也就

     是说在整个程序运行期间,它在内存中的地址是固定的,代码可以对其反复访问。C语言中的外部变量,内部静态变量就属于此类,存储

     于数据段(这些数据的地址在程序进行链接的时候就能准确算出)。另一种是“动态”的,他们在内存的地址不是固定的,对他们的操作

     就是对“栈”进行操作。

    

3、变量的声明和定义: “声明”只是告诉编译器某个标识符是:变量(什么类型?)还是函数(参数和返回值是什么?)。要是在后面的

     代码中出现该标识符,编译器就知道如何处理。声明变量不会导致编译器为这个变量分配存储空间。

4、编译与链接: 编译程序要做的事之一就是把所有需要确定地址的符号记录下来,然后链接程序在找到它们的定义点之后通过计算给予

     合适的地址。当所有的符号都有确定的地址时,链接程序就能够产生可执行文件。如果还有符号不能确定地址(找不到定义或重复定义)

     链接程序就会报错。

5、外部变量的链接性质与静态内部变量: 外部变量默认链接性质是外部的(extern),static改变外部变量的链接性质,使外部变量的

     链接性质是内部的。而对于内部变量,static改变的是其存储性质,使其可见范围不变,生存期为程序运行期间。

6、函数的声明、定义与链接性质:

7、使用头文件: 头文件应该包含:函数原型声明,全局变量的声明,自己定义的宏和类型;

                        不应该包含:全局变量和函数的定义(全局变量只能定义一次,如果你把“int global = 0;”这样的语句放在头文件)

                        则凡是包含了这个头文件的地方都定义了一次全局变量global,到了链接的时候,链接程序就会报告说找到很多歌global

                       ,不知该用哪一个。函数的情形也是这个道理,同样会产生名字冲突而导致链接失败。

                                          static变量和static函数(在全局变量声明与static变量的定义之间,static优先,于是本来应该访问一个

                        全局变量的代码,最后存取的却是一个由头文件定义的、毫无用处的static变量)。

二、

8、静态库: 静态库的结构比较简单,就是把原来的目标代码放在一起,链接的时候链接程序根据每一份目标代码的符号表查找相应的符号

     (函数和变量的名字),找到的话就把该函数里面需要定位的符号进行定位,然后将整块函数代码放进可执行文件里。

9、动态库: 动态链接就是在程序装载入内存的时候才真正把库函数代码链接进来确定它们的地址,并且就算是有多个程序运行,内存中也

     只存在一份函数代码。但动态库的数据仍然可能有多份副本。因为每一个链接到动态库的进程都可能会修改库的数据,每当出现这种情况

     的时候,操作系统就复制出一份数据的副本,然后修改进程的地址空间映射,使它指向新的数据副本,于是进程修改的知识属于自己的那

     份数据。

10、简单类型的转换: 整型之间的转换(如果被扩展变量是带符号的,那么扩展就是带符号的扩展;如果被扩展变量是不带符号的,那么

       扩展就是不带符号的扩展)。整型值转换为浮点型值不一定是安全的,浮点型值的数值范围虽然大,但却受精度的限制(不能超过6位

       有效数字)。

11、 复合类型的对齐

12、 指针: 指针数组,函数指针(存储调用函数地址,指向函数),

                   指针与数组: 指针和数组的名字都代表某种变量的地址,不同的是指针是变量,编译器会为指针分配存储空间,并且

                                      指针的值可以在运行期随意改变。

                                      数组名字只是代表某段存储空间的起始地址,数组名字相当于一个常量,编译器不会为数组名字本身分配空间,

                                      不能改变,不能改变数组名字代表的地址值。

                   数组指针,指向指针的指针,多维数组

13、 词法分析: 最大匹配原则

14、 注释:  /* */ 与 //

15、 优先级与运算顺序: 不要对运算的顺序作过多的假设。

16、 友好的typedef: 定义新的数据类型名,实际赋予别名。

                                  typedef 跟变量一样有可视范围,并且内层的可以覆盖外层的。

                                  在同一范围内,不能使用相同的名字定义不同的数据类型。

                                  #define(预编译指令)执行的仅仅是低级的符号替换,typedef是由编译器进行语法分析,用它定义的类型对

                                  声明或者定义语句中的每一个变量都起作用。

17、 C_V限定词: const在c++与c两种语言中存在差别

                            1)C++能够把(已有常量赋值的)const变量看作编译期常数,C没有这种功能。

                            2)C++默认const变量的链接性质是内部的,而C则相反,默认是外部的。

                            3)C只能允许用常量初始化const外部变量,C++没有这种限制。

                            volatile修饰一个变量的意思是告诉编译器这个变量可能会被外部事件修改,编译期在优化代码时不要擅自作出假

                            定,而导致错误的结果。

18、字符串: 字符串常量,不能被改变。指向字符串的指针 不能修改字符串。

                     可以使用字符串常量来初始化字符数组,可以修改字符数组的值。

19、void: void指针具有两个主要特性:

                  1)void指针可以和其他类型指针(函数指针除外)相互转化而不需要类型强制转换。

                  2)不能对它执行取值和下标操作。

   

                  在C++中,对类型的检查非常严格,任何指针(包括void指针)都不能不通过强制转换就直接赋值给其他指针;

                  但C++中,如果把其他类型指针的值赋给void指针,则不需要强制转换,与C一致。(void指针赋予其他指针就需要强制转

                  换)

20、 #pragma 为特定的编译器提供特定的编译指示。_Pragma


四、
21、 _Complex 与 _Imaginary

22、 内联函数: 宏仅仅是一种记号替换,不像函数,它没有办法知道真正的参数是什么,从而无法对参数进行检查,也不能像

                         函数那样把某些运算局限于内部。

                       

                         由于内联函数要求编译器在调用点尽可能地嵌入函数的代码,所以,仅仅声明一个内联函数却没有在同一文件中给出函数

                         定义的做法是没有意义的。C++明确规定,一旦使用inline声明一个函数,这个函数就成为内联函数,所有调用该函数的

                         文件都应该给出函数的定义,并且所有这些定义都应该是相同的。所以内联函数的定义一般直接放在头文件。

                         C++的inline修饰符不改变函数的链接特性,所以内联函数完全可以有外部链接特性。进一步规定,所以外部链接的内联

                         函数都必须具有相同的地址,他们内部定义的静态变量都指向同一个实体。

23、 变长数组: C99      允许数组定义的方括号内是整型变量或者是整型表达式,这样的数组称为变长数组。
                                但是,不能声明或者文件范围的外部变长数组,由于外部数组存放在数据段,它们占用的空间必须在编译期确定,所以变长数组
                                不能再函数外面声明或者定义。
                                变长数组不能是struct或union成员,因为struct和union的大小必须在编译期确定。
                                必须保证变长数组的方括号中的表达式返回整型量而且大于0,否则,后果是不确定的。
                                方括号中的表达式的求值顺序是不确定的。


24、 可伸缩数组成员: C99
                                在struct中使用可伸缩数组成员:
                                 1)数组元素地址的有效性完全由程序员负责。
                                 2)包含可伸缩数组成员的struct至少要另外一个包含一个编译期可确定大小的成员,并且可伸缩数组成员在struct中必须是最后
                                    一个成员。
                                 3)不管任何时候,压栈和赋值操作都不会把可伸缩数组成员包含在内。
                                 4)在动态分配内存之前可伸缩数组成员不占用任何存储空间,所以我们无法对可伸缩数组成员进行初始化。

25、 Designated Initializer 机制: 可以随便选择结构体中的某个(些)元素进行初始化。
26、 Compound Literal: 匿名对象(type){value,...}如果匿名对象出现在函数的外面,则它具有静态存储特性,放在数据段(并且具有内部链接性质);
                                            否则它就具有自动存储特性,存储在栈中,和普通对象一样,其初始化列表中可以包含非常量表达式。
27、 Restricted Pointer: restrict 修饰指针主要是为了通知编译器,这个指针指向的内存区域和其他同样用restrict修饰的指针指向的内存区域
                                           不存在重叠,于是编译器可以根据具体情况决定是否对代码进行优化编译。

28、 数值运算: limit.h (具体某个平台上C编译器对整型类型所占字节数的规定)
                                stdint.h(文件中包含了一系列关于统一的、标准的整数类型的宏定义,通过使用这些宏,能够保证在各种平台上得到统一的整数
                                           类型)
                                float.h(定义了系统的浮点数类型的相关特性,例如指数、有效位数、各种浮点类型的最大最小值、舍入方式等)

29、字符集与字符编码: 源代码字符集(用于编写C源代码的字符所组成的集合)
                                              执行字符集(程序执行时能够被系统环境正确解释的字符所组成的集合)。 三联符、 二联符、 UCS字符!!!

 

 五、

30、C++的函数: C++允许函数重载,为了实现这项特性,C++编译器必须有某种方法区分哪些名字相同但参数不同的函数,像C编译器那样仅仅
                                 把函数名字作为汇编符号肯定是不行的。解决问题的方案是通过编码把参数的信息融入到最终输出的汇编符号中。
                                 由于C++对函数名字的处理,我们如果要调用C的库函数,就必须明确告诉C++编译器,通知它不要扩展函数名:extern “C”。

31、 名字空间:  提供一种逻辑分割的方法把全局空间分解开从而避免大量的名字冲突。与函数重载的实现同理,输出汇编代码时,C++编译器把
                                 名字空间的信息编进最终的符号中。

32、 C和C++的标准库: 

33、 模板: 

34、 外部对象的初始化: 在C语言(C90和C99)中,规定必须用常量表达式去初始化外部变量。
                                                在C++中,可以使用非常量表达式初始化外部变量(对象)。
                                                由于初始化对象一般需要调用类的构造函数,所以,对于C++编译器来说,允许使用非常量表达式初始化外部变量(对
                                                象),就必须允许在进入main函数前调用某些用户定义的函数,这些函数的代码比main函数更早运行。
                                

 

 

 

 

 

 

 

 

posted @ 2009-12-08 01:19 HenDanTou 阅读(341) | 评论 (0)编辑 收藏
仅列出标题