一、程序设计基础概念
1、在c++程序中调用被c编译器编译后的函数,为什么要加extern “C”?
c++语言支持函数重载,c语言不支持函数重载。函数被c++编译后在库中的名字与c语言的不同。假设某个函数的原型为voidf oo(int x,int y)。该函数被c编译器编译后再库中的名字为_foo,而c++编译器则会产生像_foo_int_int 之类的名字。
c++提供了c连续交换指定符号extern“C”解决名字匹配的问题。
2、头文件中的ifdef/define/endif是干什么用的?
头文件中的ifdef/define/endif是条件编译的一种,除了头文件被防止重复引用(整体),还可以防止重复定义(变量、宏或者结构)。
3、评价一下c与c++的各自特点。如果一个程序既需要大量运算,又要有一个好的用户界面,还需要与其他软件大量交流,应该怎样选择合适的语言?
c是一种结构化语言,重点在于算法和数据结构。c程序的设计首先考虑的是如何通过一个过程,对输入(或者环境条件)进行运算处理得到输出(或实现过程(事务)控制),而对于c++,首先考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。
对于大规模数值运算,c/c++和java/.NET之间没有明显的性能差异。不过,如果运算设计向量计算、矩阵运算,可以使用FORTRAN或者MATLAB编写计算组件(如COM)。
大规模用户界面的相关的软件可以考虑使用.NET进行开发(Windows环境下),而且.NET同COM之间的互操作十分容易,同时.NET对数据库访问的支持也相当好。
二、预处理、const与sizeof
1、宏定义
2、const
关于const修饰指针,一般分为以下四种情况:
int b=500;
const int* a=&b; //情况1
int const *a=&b; //情况2
int* const a=&b; //情况3
const int* const a=&b; //情况4
1)如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号右侧,const就是修饰指针本身,即指针本身是常量。
1、const与#define相比有什么不同
c++语言可以用const定义常量,也可以用#define定义常量,但是前者比后者有更多优点:
a.const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换中可能会产生意料不到的错误(边际效应)。
b.有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。在c++程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。
2、数据对齐
数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍。DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽。x86CPU能直接访问对齐的数据
3、sizeof与strlen的区别
a.sizeof操作符的结果类型是size_t,它在头文件中的typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。
b.sizeof是运算符,strlen是函数
c.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以“\0”结尾的。sizeof还可以用函数做参数
c.数组做sizeof的参数不退化,传递给strlen就退化为指针
e.大部分编译程序在编译的时候就把sizeof计算过了,是类型或是变量的长度。这就是sizeof(x)可以用来定义数组维数的原因。
f.strlen的结果要在运行的时候才能计算出来,用来计算字符串的长度,而不是类型占内存的大小
g.sizeof后如果是类型必须加括号,如果是变量名可以不加括号。这是因为sizeof是个操作符而不是个函数。
h.当使用了一个结构类型或变量时,sizeof返回实际的大小。当使用一静态的空间数组时,sizeof返回全部数组的尺寸。sizeof操作符不能返回被动态分配的数组或外部的数组的尺寸。
i.数组作为参数传给函数时传递的是指针而不是数组,传递的是数组的首地址,如fun(char[8]、fun(char [])都等价于fun(char *))。在c++里传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小。如果想在函数内知道数组的大小,需要这样做:进入函数后用memcpy将数组赋值出来,长度由另一个形参传进去。
j.计算结构变量的大小就必须讨论数据对齐问题。为了使CPU存取的速度最快,c++在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,这就叫数据对齐。这样做可能会浪费一些内存,但在理论上CPU速度快了。当然,这样的设置会在读写一些别的应用程序生成的数据问津或交换数据时带来不便。
k.sizeof操作符不能用于函数类型、不完全类型或位字段。不完全类型指具有未知存储大小数据的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。
4、说明sizeof的使用场合
a.sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。
b.用它可以看看某种类型的对象在内存中所占的单元字节。
c.在动态分配一对象时,可以让系统知道要分配多少内存。
d.便于一些类型的扩充。在windows中有很多结构类型就有一个专用的字段用来存放该类型的字节大小。
e.由于操作数的字节数在实现时可能出现变化,建议在涉及操作数字节大小时用sizeof代替常量计算。
f.如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。
5、各个类型数据所占字节数
取值范围 占字节数空类所占空间为1字节,单一继承的空类空间为1字节,多重继承的空类还是1字节。虚继承涉及虚表(虚指针),所以占空间大小为4字节。
6、内联函数和宏定义
内联函数是指用inline关键字修饰的函数。在类内定义的函数被默认成内联函数。内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质。内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处。编译时,类似宏替换,使用函数体替换调用处的函数名。一般在代码中用inline修饰,但是能否形成内联函数,需要看编译器对该函数定义的具体处理。
a.内联函数和宏定义的差别是什么?
内联函数和普通函数相比可以加快程序运行的速度,因为不需要中断调用,在编译的时候内联函数可以直接被镶嵌到目标代码中。而宏只是一个简单的替换。
内联函数要做参数类型检查,这是内联函数跟宏相比的优势。
inline是指嵌入代码,就是在调用函数的地方不是跳转,而是直接把代码直接写到那里去。对于短小的代码来说inline增加空间消耗换来的是效率提高,这方面和宏是一模一样的,但是inline在和宏相比没有付出任何额外代价的情况下更安全。至于是否需要inline函数,就需要根据实际情况来取舍。
inline一般只用于如下情况:
(1)一个函数不断被重复调用。
(2)函数只有简单的几行,且函数内不包含for、while、switch语句。
一般来说,我们写小程序没有必要定义成inline,但是如果完成一个工程项目,当一个简单函数被调用多次时,则应该考虑inline。
关键字inline必须与函数定义体放在一起才能使函数成为内联。
网友评论