`
celebration
  • 浏览: 34997 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

C/C++ 笔试、面试题目(1)

阅读更多

1.求下面函数的返回值(微软)

int func(x) {        int countx = 0;        while(x)        {              countx ++;              x = x&(x-1);         }        return countx; }  

假定x = 9999。 答案:8

思路:将x转化为2进制,看含有的1的个数。

2. 什么是“引用”?申明和使用“引用”要注意哪些问题?

答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进行初始化。引用 声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表 示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。

3. 将“引用”作为函数参数有哪些特点?

(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。

(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参 分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和 所占空间都好。

(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式 进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

4. 在什么时候需要使用“常引用”? 

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名;

例1

int a ; const int &ra=a; ra=1; //错误 a=1; //正确

例2

string foo( ); void bar(string & s);

那么下面的表达式将是非法的:

bar(foo( )); bar("hello world");

原因在于foo( )和"hello world"串都会产生一个临时对象,而在C++中,这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。

引用型参数应该在能被定义为const的情况下,尽量定义为const 。

5. 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?

格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }

好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!

注意事项:

(1)不能返回局部变量的引用。这条可以参照Effective C++[1]的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。

(2)不能返回函数内部new分配的内存的引用。这条可以参照Effective C++[1]的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。

(3)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常 量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。

(4)流操作符重载返回值申明为“引用”的作用:

流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回 一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一 个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这 就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。

例3

#i nclude <iostream.h> int &put(int n); int vals[10]; int error=-1; void main() { put(0)=10; //以put(0)函数值作为左值,等价于vals[0]=10; put(9)=20; //以put(9)函数值作为左值,等价于vals[9]=20; cout<<vals[0]; cout<<vals[9]; } int &put(int n) { if (n>=0 && n<=9 ) return vals[n]; else { cout<<"subscript error"; return error; } }

(5)在另外的一些操作符中,却千万不能返回引用:+-*/ 四则运算符。它们不能返回引用,Effective C++[1]的Item23详细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一 个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。所以可选的只剩下返回一个对象了。

6. “引用”与多态的关系?

引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。

例4

Class A; Class B : Class A{...};     B b; A& ref = b;

7. “引用”与指针的区别是什么?

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。此外,就是上面提到的对函数传ref和pointer的区别。

8. 什么时候需要“引用”?

流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。

以上 2-8 参考:http://blog.csdn.net/wfwd/archive/2006/05/30/763551.aspx

9. 结构与联合有和区别? 1. 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。 2. 对于联合的不同成员赋值, 将会对其它成员重写,     原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。

10. 下面关于“联合”的题目的输出?

a)

#i nclude <stdio.h> union { int i; char x[2]; }a;

void main() { a.x[0] = 10; a.x[1] = 1; printf("%d",a.i); } 答案:266 (低位低地址,高位高地址,内存占用情况是Ox010A)

b)

        main()         {              union{                      /*定义一个联合*/                   int i;                   struct{                /*在联合中定义一个结构*/                        char first;                        char second;                   }half;              }number;              number.i=0x4241;            /*联合成员赋值*/              printf("%c%c\n", number.half.first, mumber.half.second);              number.half.first='a';      /*联合中结构成员赋值*/              number.half.second='b';              printf("%x\n", number.i);              getch();         } 答案: AB      (0x41对应'A',是低位;Ox42对应'B',是高位)

          6261 (number.i和number.half共用一块地址空间)

11. 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数,请编写函数 strcpy。

答案: char *strcpy(char *strDest, const char *strSrc) { if ( strDest == NULL || strSrc == NULL) return NULL ; if ( strDest == strSrc) return strDest ; char *tempptr = strDest ; while( (*strDest++ = *strSrc++) != ‘\0’) ; return tempptr ; }

12. 已知String类定义如下:

class String { public: String(const char *str = NULL); // 通用构造函数 String(const String &another); // 拷贝构造函数 ~ String(); // 析构函数 String & operater =(const String &rhs); // 赋值函数 private: char *m_data; // 用于保存字符串 };

尝试写出类的成员函数实现。

答案:

String::String(const char *str) {       if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断         {           m_data = new char[1] ;           m_data[0] = '\0' ;         }       else        {           m_data = new char[strlen(str) + 1];           strcpy(m_data,str);        }

}

String::String(const String &another) {        m_data = new char[strlen(another.m_data) + 1];        strcpy(m_data,other.m_data); }

String& String::operator =(const String &rhs) {        if ( this == &rhs)            return *this ;        delete []m_data; //删除原来的数据,新开一块内存        m_data = new char[strlen(rhs.m_data) + 1];        strcpy(m_data,rhs.m_data);        return *this ; }

String::~String() {        delete []m_data ; }

13. .h头文件中的ifndef/define/endif 的作用?

答:防止该头文件被重复引用。

14. #i nclude<file.h> 与 #i nclude "file.h"的区别?

答:前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。

15.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?

首先,作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。

通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和 函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块 A编译生成的目标代码中找到此函数

extern "C"是连接申明(linkage declaration),被extern "C"修饰的变量和函数是按照C语言方式编译和连接的,来看看C++中对类似C的函数是怎样编译的:

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:

void foo( int x, int y );

该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。

_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数 void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。

同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本 质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

未加extern "C"声明时的连接方式

假设在C++中,模块A的头文件如下:

// 模块A头文件 moduleA.h #ifndef MODULE_A_H #define MODULE_A_H int foo( int x, int y ); #endif  

在模块B中引用该函数:

// 模块B实现文件 moduleB.cpp #i nclude "moduleA.h" foo(2,3);

实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!

加extern "C"声明后的编译和连接方式

加extern "C"声明后,模块A的头文件变为:

// 模块A头文件 moduleA.h #ifndef MODULE_A_H #define MODULE_A_H extern "C" int foo( int x, int y ); #endif  

在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:(1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

(2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。

所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么 做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):实现C++与C及其它语言的混合编程。  

明白了C++中extern "C"的设立动机,我们下面来具体分析extern "C"通常的使用技巧:

extern "C"的惯用法

(1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:

extern "C" { #i nclude "cExample.h" }

而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。

C++引用C函数例子工程中包含的三个文件的源代码如下:

/* c语言头文件:cExample.h */ #ifndef C_EXAMPLE_H #define C_EXAMPLE_H extern int add(int x,int y); #endif

/* c语言实现文件:cExample.c */ #i nclude "cExample.h" int add( int x, int y ) { return x + y; }

// c++实现文件,调用add:cppFile.cpp extern "C" { #i nclude "cExample.h" } int main(int argc, char* argv[]) { add(2,3); return 0; }

如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C" { }。

(2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。

C引用C++函数例子工程中包含的三个文件的源代码如下:

//C++头文件 cppExample.h #ifndef CPP_EXAMPLE_H #define CPP_EXAMPLE_H extern "C" int add( int x, int y ); #endif

//C++实现文件 cppExample.cpp #i nclude "cppExample.h" int add( int x, int y ) { return x + y; }

/* C实现文件 cFile.c /* 这样会编译出错:#i nclude "cExample.h" */ extern int add( int x, int y ); int main( int argc, char* argv[] ) { add( 2, 3 ); return 0; }

15题目的解答请参考《C++中extern “C”含义深层探索》注解:

16. 关联、聚合(Aggregation)以及组合(Composition)的区别?

涉及到UML中的一些概念:关联是表示两个类的一般性联系,比如“学生”和“老师”就是一种关联关系;聚合表示has-a的关系,是一种相对松散的关系,聚合类不需要对被聚合类负责,如下图所示,用空的菱形表示聚合关系:

                           

从实现的角度讲,聚合可以表示为:

class A {...}     class B { A* a; .....}

而组合表示contains-a的关系,关联性强于聚合:组合类与被组合类有相同的生命周期,组合类要对被组合类负责,采用实心的菱形表示组合关系:

                            

实现的形式是:

class A{...} class B{ A a; ...}

分享到:
评论

相关推荐

    c/c++ 笔试面试题

    从标题"C/C++ 笔试面试题"和描述"搜集的C/C++笔试面试经典题目,有100多页doc"可以看出,这是一份C/C++语言的笔试面试题目集锦。 从标签"C C++ 笔试 面试"可以看出,这份文件的主要内容是关于C/C++语言的笔试和面试...

    C/C++笔试面试题目大汇总

    ### C/C++笔试面试题目大汇总 #### 1. 求下面函数的返回值(微软) 函数示例代码如下: ```c++ int func(int x) { int count_x = 0; while (x) { count_x++; x = x & (x - 1); } return count_x; } ``` ...

    c/c++面试笔试题目深度解析

    在C/C++面试和笔试中,常常会遇到各种各样的问题,这有助于考察应聘者对这两种编程语言的理解和掌握程度。下面将针对题目中的几个关键知识点进行深入解析: 1. **字符串比较**: - `str1` 和 `str2` 是字符数组,...

    C/C++ 笔试、面试题目大汇总

    从给定的文件信息中,我们可以总结出一系列关于C/C++编程语言的重要知识点,特别是针对笔试和面试场景下的常见问题。以下是对标题、描述、标签和部分内容中提及的知识点的详细解析: ### 1. 函数返回值计算 在微软...

    大量C/C++笔试题

    这份“大量C/C++笔试题”集合涵盖了从基础知识到深入概念的各种问题,旨在帮助求职者在面试过程中表现出色。以下是一些重要的C/C++知识点,结合题目可能会涉及到的内容进行详尽阐述。 1. **基本语法**:这是C/C++...

    C/C++ 笔试面试题

    标题中的"C/C++ 笔试面试题"表明这是一个关于C++编程语言的面试及笔试问题集合,主要针对求职者在找工作时可能会遇到的技术考察。这些题目通常涵盖C++的基础概念、语法、数据结构、算法、面向对象编程、模板、异常...

    2009华为-百度C/C++笔试题目

    "2009华为-百度C/C++笔试题目"这一标题揭示了这次笔试的主题,涉及的是两大知名IT公司——华为和百度在2009年招聘过程中针对C/C++编程语言的笔试环节。这通常包括对C/C++语言基础、算法、数据结构、操作系统原理等多...

    c/c++笔试、面试题目

    C/C++ 笔试、面试题目大汇总 本资源摘要信息总结了 C/C++ 语言的笔试和面试题目,涵盖了函数返回值、引用、函数参数、常引用和返回值类型等方面的知识点。 一、函数返回值 * 问题 1:求下面函数的返回值(微软) ...

    C/C++笔试题集锦

    《C/C++笔试题集锦》是一份涵盖了广泛C/C++知识的资源,旨在帮助求职者准备相关的技术面试和笔试。这份资料不仅包含了常见的C/C++编程题目,还深入探讨了语言的一些关键概念,如类型转换和对象模型,这对于理解和...

    C/C++笔试题目常见题目

    总的来说,C/C++笔试题目通常涉及基础数据结构操作(如链表)、对象生命周期管理(如拷贝构造和赋值运算符重载)以及语言特性(如引用)。理解并熟练掌握这些知识点对于准备C/C++相关的面试至关重要。

    C/C++笔试题目大全收藏

    C/C++编程语言中的笔试题目常常涉及到核心概念和技巧,如上述题目所示。第一题考察了位操作,通过`x = x&(x-1)`这一句,实际上是在消除x二进制表示中最右边的一个1,每次循环都会减少一个1,直到x变为0。因此,对于...

    史上最全的C/C++笔试和面试题

    "史上最全的C/C++笔试和面试题"这个压缩包文件显然是为那些准备进入IT行业,特别是想在C/C++领域发展的求职者准备的资源。它可能包含了从基础到高级的各种题目,涵盖了语言特性、数据结构、算法、操作系统原理等多个...

    c/c++笔试题目

    C/C++笔试题目是衡量和提升开发者编程技能的重要方式,尤其在招聘过程中...以上是C/C++笔试题目中可能涉及的一些关键知识点,深入理解和熟练掌握这些内容将有助于提高你的编程技能,使你在面试或实际工作中更具竞争力。

    C/C++笔试面试题

    在C/C++编程领域,笔试面试题通常涵盖了语言的基础、高级特性和常见编程陷阱。以下是一些基于给定文件中的知识点的详细解释: 1. **预处理指令#define**: - `#define`用于创建宏定义,允许我们将常量或模板代码...

    C/C++笔试、面试题目和答案大汇总.doc

    在C/C++编程语言的学习和求职过程中,理解和掌握一些常见的笔试和面试题目至关重要。以下是针对题目和答案的一些详细解析: 1. 函数`func(x)`的返回值计算: 这是一个经典的位操作题。函数`func(x)`通过`x = x & ...

    c&c++笔试宝典,各大软件公司的笔试题目都差不多,掌握了里面的内容,c/c++笔试100%过!!!!

    《C&C++笔试宝典》是一本专门为准备C++和C语言笔试的求职者精心编纂的指南。这本书涵盖了各种软件公司常...对于求职者来说,这本书无疑是一把打开软件公司大门的金钥匙,只要用心研读,顺利通过C/C++笔试将不再是难题。

    C/C++笔试面试宝典大全

    这里整理了几份比较新的C及C++的笔试面试题目(不少企业的考题是直接来自于上面的题目),适合找软件开发、嵌入式开发方面工作的朋友,许多公司的面试都有笔试部分,当你吃透了这几份文档的题目,你完全可以轻松过...

    c/c++经典笔试题目

    以下是一些典型的C/C++笔试题目及其解析。 1. 求下面函数的返回值(微软) ```cpp int func(x){ int countx = 0; while(x){ countx++; x = x&(x-1); } return countx; } ``` 假定 x = 9999。答案:8 这...

    C/C++笔试题(全)word文档 流传笔试题汇总

    【C/C++笔试题解析】 在C/C++的笔试题中,常见的问题涵盖了语言的各个方面,包括基础语法、数据结构、算法以及特定概念的理解。以下是对一些常见知识点的详细解释: 1. **位操作**: - 题目1中的`func(x)`函数...

Global site tag (gtag.js) - Google Analytics