Chinaunix首页 | 论坛 | 博客
  • 博客访问: 631121
  • 博文数量: 87
  • 博客积分: 3399
  • 博客等级: 中校
  • 技术积分: 1422
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-17 21:20
文章分类

全部博文(87)

文章存档

2013年(1)

2012年(51)

2011年(33)

2010年(2)

分类: C/C++

2011-10-13 22:05:29

6 预处理、constsizeof 6.1 宏定义

6.1 宏定义

1)用宏定义FIND来定义一个结构体struc里某个变量相对struc的偏移量。

Eg: struct student{ int a, char b[20], double ccc};

FIND(student, a)=0; FIND(student, b)=4;

Notes:

A: #define FIND(struc, e) ((size_t)&(((struc*)0)->e))

(struc*)0 表示将常量0强制转换成struc* 型指针所指向的地址 &(((struc*)0)->e)表示取结构体指针(struc*)0的成员e的地址,因其首地址为0,故可得成员e距离结构体首地址的偏移量。Size_t为一个基本的无符号整数的C / C + +类型。 它是sizeof操作符返回的结果类型。在C++中,设计 size_t 就是为了适应多个平台的 size_t的引入增强了程序在不同平台上的可移植性。size_t是针对系统定制的一种数据类型。

2)用宏定义声明一个常数表明一年中有多少秒(忽略闰年问题)。

Notes:

A: #define SECONDS_PER_YEAR (365*24*60*60UL)

a. 使用括号 b.名字定义 c.考虑溢出用长整型

3)用宏定义实现取两个参数中较小的一个:

A: #define MIN(A,B) ((A)<=(B) ? (A) : (B))

6.2 const

1const 作用:、

a. 可以定义常量。b.可以修饰函数参数和返回值,甚至函数的定义体,被const修饰后,受到强制保护,可以预防意外的变动,提高程序健壮性。

2const较之于宏定义的优点:

a. const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只有字符替换,可能产生意料不到的错误。

b.const常量便于追踪,可调试,宏常量不便调试。

3const var; c中是对的,c编译器把它看作一个声明,这个声明指明在别的地方有内存分配;而在c++中编译无法通过,常量必须在定义时初始化!c默认const是外部链接的,c++默认const是内部链接的,为了在c++中完成同样的事情必须用extern将内部链接改成外部链接: extern const var; c中最好用宏定义,在c++const声明常量。

4)在c++中,类中的函数用const修饰了,则此函数为恒态函数,不可以改变类中的数据成员。如果确实要改变,则在数据成员前用mutable 修饰。

6.3 sizeof

1

struct {short a1;       short a2;  short a3;}A;

struct{long a1;          short a2;}B;

class C{double d;      float f;      int i; short s;    char c;};

class D{int a;    static int b;};

class E{private:         bool a;      int b;         bool c;};

class F{private:         int b;         bool a;               bool c;};

int main()

{

         char* ss1 = "0123456789";

         char ss2[] = "0123456789";

         char ss3[100] = "0123456789";

         int ss4[100];

         char q1[]="abc";

         char q2[]="a\n";

         char* q3="a\n";

         char *str1 = (char*)malloc(100);

         void *str2 = (void*)malloc(100);

 

         cout<

         cout<

         cout<

         cout<

         cout<

         cout<

         cout<

         cout<

         cout<

         cout<

         cout<

         cout<8为对齐参数

         cout<sizeof 计算栈中分配的大小

//静态变量存放在全局数据区,不被计算

         cout<

cout<

int i = 1;

cout<是操作符,后面跟变量名可不加括号

         return 0;

}

Notes

结构体的内存空间

a. 当结构体内元素的长度都小于处理器的位数时:

         以结构体内最长的数据元素为对齐单位,即结构体的长度一定是最长数据元素的整数倍。

b. 当结构体内存在长度大于处理器位数的元素时,以处理器的位数为对齐单位,但是结构体内类型相同的连续元素将在连续的空间内。

内存中的数据对齐:

数据对齐是指,数据所在的内存地址是该数据长度的整数倍。Eg: DWORD数据的内存起始地址能被4整除,WORD数据的内存起始地址能被2整除。

禁用数据对齐:vc中可以pack指令禁止对齐调整#param pack1 struct astruct{char c; int i;} #param pack() … cout<如果不用该指令则为8

一般禁用调整会影响程序性能,常用情况是:

a.这个结构需存入文件 b.这个结构需要通过网络传播

2sizeof的使用场合:

a.查看某种类型的对象在内存中所占的单元字节

b.动态分配一对象时,使系统知道要分配多少内存

c.操作数的字节数在实现时可能出现变化,可用sizeof代替常量计算

d.与存储分配和I/O系统那样的进程通信: void * malloc(size_t size); size_t fread(void *ptr,size_t size,size_t n,FILE * stream);

3sizeof strlen的区别:

a. sizeof 用来计算操纵数所占内存大小,strlen用来计算字符串长度。sizeof不是函数也不是一元运算符,是个类似于宏定义的特殊关键字sizeof()括号内的内容在编译过程中不被编译,只是被替代为类型eg: int a = 8; cout<

strlen 的内部实现为:用一个循环计算字符串的长度,直到遇到“\0”为止。

sizeof 可以看作算符,strlen是函数,故strlen后面必须加括号,而sizeof后面跟类型时需加括号,跟变量名时不需加括号

         b.sizeof 可以用类型、变量名、甚至函数作参数,strlen只能用以“\0”结尾的char*作参数。char fun(); cout<返回值类型的大小

         c.sizeof的结果类型为size_t,它在头文件中被typedefunsigned int

         d.数组做参数传递给sizeof时不退化,传递给strlen时退化为指针:char ch[15]=”123”;

         cout<  4

e.unsigned影响的是最高位bit的意义,数据长度不会被改变,sizeof(unsigned type) = sizeof(type),有个例外:vc 6.0 中,         cout<

cout<

         f.一般在编译时就计算过sizeof了,运行时才知道strlen的结果。

         g.sizeof不能用于不完全类型或位字段。不完全类型是指具有未知存储大小数据的数据类型,如未知存储大小的数组、结构、联合以及void类型。

4)数组作为参数传递到函数内时,退化为一个指针。

5class A{};

class A1{};

class B: public A{};

class C: public virtual B{};

class D: public A,public A1{};

void main()

{

         cout<

         cout<

         cout<

         cout<

}

Notes:

一个空类所占的空间为1,一个单一继承的空类空间也为1,多重继承的空类空间也未1,但是虚继承因涉及到虚表(虚指针),所占的空间为4

6

         string strArr[]={"hello","jia","leo"};

         string *pStrArr=new string[2];

         pStrArr[0] = "CN";

         pStrArr[1] = "US";

         cout<16

         cout<48

         cout<

         for(int i=0; i

         {cout<

         for(int j=0; j

         {cout<

         for(int k=0; k<sizeof(*pStrArr)*2/sizeof(string); k++)

         {cout<为数组成员的类型-string

6.4 内联函数和宏定义

内联函数是在编译时直接将函数体嵌入到目标代码中,不用中断,减少了函数调用的开销,可提高程序运行效率。适用情况是a.函数被重复调用b.函数短小简单,一般不含for/switch/while函数。

宏是在编译前将相关字符串替换成宏体,只是简单替换没有验证。

内联函数比宏的优势是,要做类型检查。

阅读(2245) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~