您的位置:首页 > 编程语言 > C语言/C++

C++程序员要掌握的问题集锦

2011-07-21 11:10 337 查看
Q:请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句

A:define max(a,b) ( a/b)?a:b

//---------------------------------------------------------------------------------------

Q:写一个病毒

A:

while (1)

{

int *p = new int[10000000];

}

//---------------------------------------------------------------------------------------

Q:有A、B、C、D四个人,要在夜里过一座桥。他们通过这座桥分别需要耗时1、2、5、10分钟,只有

一支手电,并且同时最多只能两个人一起过桥。请问,如何安排,能够在17分钟内这四个人都过桥?

A:

答案:

第一步:A(1)和B(2)过桥,A(1)返回 Cost:1+2

第二步: C(5)和D(10)过桥,B(2)返回 Cost:10+2

第三步: A(1)和B(2)过桥 Cost:2

//---------------------------------------------------------------------------------------

Q:实现strlen函数,不许用任何变量~

A:

#include <iostream>

#include <stdio.h>

#include <stdlib.h>

#include <string>

using namespace std;

int myStrlen(const char *str)

{

return *str ? ( *(str+1) ? ( 1 + myStrlen(str+1) ) : 1 ) : 0 ;

}

int main()

{

char *orig = "Hello, World!";

cout << orig << " (char *)" << endl;

cout << myStrlen(orig) << endl;

return 0;

}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

把 *str ? ( *(str+1) ? ( 1 + myStrlen(str+1) ) : 1 ) : 0 展开来

int myStrlen(const char *str)

{

if( *str != 0 )

{

if( *(str+1) != 0 )

{

return ( 1 + myStrlen(str+1) );

}

else

{

return 1;

}

}

else

{

return 0;

}

}

//---------------------------------------------------------------------------------------

Q:用递归写出 x! = x * (x-1) * (x-2) * (x-3) * ... * 2 * 1

A:

unsigned short factorial(unsigned short a);

int main(void)

{

int num;

int total;

cout<<"请输入数据: "<<endl;

cin>>num;

total = factorial(num);

cout<<"结果为: "<<total<<endl;

return 0;

}

factorial(a)

{

if( a == 1 )

{

return 1;

}

else

{

a *= factorial(a-1);

return a;

}

}

//---------------------------------------------------------------------------------------

Q:下列哪两个是等同的

int b;

A const int* a = &b;

B const* int a = &b;

C const int* const a = &b;

D int const* const a = &b;

答: (C = D) 这两个是等同的 都表示常量指针常量(指针本身是常量,而且所指内容也是常量)

A const int* a = &b; //常量指针,只能够读出内存的数据,却不能修改内存的数据。

B const* int a = &b; //非法的。

C const int* const a = &b; //内存数据和指针的地址都不能够修改

D int const* const a = &b; //内存数据和指针的地址都不能够修改

E int * const a = &b; //指针常量,指针的地址不能够修改,只能指向b。

//---------------------------------------------------------------------------------------

Q:内联函数在编译时是否做参数类型检查?

void g(base & b)

{

b.play;

}

void main()

{

son s;

g(s);

return;

}

A:

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

//---------------------------------------------------------------------------------------

Q:C++函数中值的传递方式有哪几种?

A:

C++函数中值的传递有三种传递方式:1.值传递 2.指针传递 3.引用传递

//---------------------------------------------------------------------------------------

Q:头文件的作用是什么?

A:

1.通过头文件调用程序库功能,用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的,编译器会从程序库里提取相应的代码。

2.加强类型的安全检查,函数或者接口被使用时候,方式和头文件中的声明不一致,编译器会之处错误。

//---------------------------------------------------------------------------------------

Q:内存的分配方式的分配方式有几种?

A:

1.从静态存储区域分配,内存编译的时候就已经分配好了,这块内存在程序的整个运行期间都存在,例如:全局变量,静态变量。

2.在栈上创建,在执行函数时,函数内局部变量的存储单元可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内分配运算内置于处理器的指令集中,效率很高,但是分配内存容量有限。

3.从堆上分配,亦称动态内存分配。程序运行的时候用malloc或new申请任意多少的内存,程序员自己负责在任何时用free或delete释放内存。

//---------------------------------------------------------------------------------------

Q:实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数;

A:

typedef struct DNode

{

int date;

DNode * prior;

DNode * next;

};

DNode * DList;

void insertNode(DList &list, int pValue)

{

DList p = list;

if( p == NULL )

return;

while( p->date != pValue )

{

p = p->next;

}

DNode *q = new DNode();

p->date = pValue;

p->next->prior = q;

q->next = p->next;

p->next = q;

q->prior = p;

}

void deleteNode(DList &list, int pValue)

{

DList p = list;

if( p == NULL )

return;

while( p->date != NULL )

{

p = p->next;

}

p->prior->next = p->next;

p->next->prior = p->prior;

//free p;

delete p;

}

//---------------------------------------------------------------------------------------

Q:C++里面是不是所有的动作都是main()引起的?如果不是,请举例.

A:

当然不是所有的动作都是main()引起的,只是编译器由main()开始执行的

静态变量和全局变量的分配早在main之前完成

内联,模板,函数声明,宏的扩展全是预编译期行为,也不是main()完成的

注:C++和main()逻辑上没有必然的联系。

//---------------------------------------------------------------------------------------

Q:如何定义和实现一个类的成员函数为回调函数?

A:

把成员函数申明为static就可以了。

//---------------------------------------------------------------------------------------

Q:C++里面如何声明const void f(void)函数为C程序中的库函数?

A:

extern "C" void f(void);

所以extern "C"是强迫C++编译器对函数名进行修饰的时候采用C命名约定。

//---------------------------------------------------------------------------------------

Q:Windows程序的入口是哪里?写出Windows消息机制的流程。

A:

入口点是WinMain函数.

Windows消息机制的流程:

1.Windows中有一个系统消息队列,对于每一个正在执行的Windows应用程序,系统为其建立一个“消息队列”,即应用程序队列,用来存放该程序可能创建的各种窗口的消息。应用程序中含有一段称作“消息循环”的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中。

2.Windows为当前执行的每个Windows程序维护一个「消息队列」。在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中。程序通过执行一块称之为「消息循环」的程序代码从消息队列中取出消息:

while(GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

TranslateMessage(&msg);将msg结构传给Windows,进行一些键盘转换。

DispatchMessage (&msg);又将msg结构回传给Windows。然后,Windows将该消息发送给适当的窗口消息处理程序,让它进行处理。

SendMessage()与PostMessage()之间的区别是什么?

它们两者是用于向应用程序发送消息的。PostMessagex()将消息直接加入到应用程序的消息队列中,不等程序返回就退出;而SendMessage()则刚好相反,应用程序处理完此消息后,它才返回。

//---------------------------------------------------------------------------------------

Q:把一个链表反向填空

A:

void reverse(test* head)

{

test* pe = head;

test* ps = head->next;

while(ps)

{

//方法一 pe是固定不动

pe->next = ps->next;

ps->next = head;

head = ps;

ps = pe->next;

//方法二 pe ps head 都向后移动

//head = ps->next;

//ps->next = pe;

//pe = ps;

//ps = head;

}

}

//---------------------------------------------------------------------------------------

Q:什么函数不能成为虚函数?

A:

构造函数()

内联函数(因为没有函数地址,在编译时插入,是个静态行为。)

静态成员函数(因为静态成员函数类似于全局函数,但是属于相应的类,在相应类的作用域下,没有this指针)

//--------------------------------------------------------------------------------------

Q:虚函数与接口的区别?

A:

虚函数的概念:

虚函数是动态联编的基础,它是引入派生概念之后用来表现基类和派生类成员函数之间的一种关系。虚函数在基类中定义,它也是一种成员函数,而且非静态成员函数。

若一个实例方法的声明中含有virtual修饰符,则称该方法为虚拟方法;一个虚拟方法的实现可以派生类取代。取代所继承的虚拟方法的实现的过程称为重写(覆盖)该方法;在一个虚拟方法调用中,该调用所涉及的那个实例的运行时类型确定了要被调用的究竟是该方法的哪一个实现。

虚函数的限制:

1.虚函数仅适用于有继承关系的类对象,所以只有类的成员函数才能说明为虚函数。

2.静态成员函数不能是虚函数。

3.内联函数不能是虚函数。

4.构造函数不能是虚函数。

5.析构函数可以是虚函数。

接口可以有静态成员、嵌套类型、抽象、虚拟成员、属性和事件。实现接口的任何类都必须提供接口中所声明的抽象成员的定义。接口可以要求任何实现类必须实现一个或多个其他接口。

对接口有以下限制:

接口可以任何可访问性来声明,但接口成员必须全都具有公共可访问性。

不能向成员或接口自身附加安全性权限。

接口可以定义类构造函数,但不能定义实例构造函数。

每种语言都必须为需要成员的接口映射一个实现提供规则,因为不只一个接口可以用相同的签名声明成员,且这些成员可以有单独的实现。

接口可以有类和结构来实现。为了只是类或结构实现了某接口,在该类或结构的基类列表中应该包含该接口的标识符。如果一个类或结构实现某接口,则它还隐式实现该接口的所有基接口。即使在类或结构的基类列表中没有显式列出所有基类接口,也是这样。

//--------------------------------------------------------------------------------------

Q:C++中虚函数怎么实现的?

A:

每个定义了虚函数的类都有一张虚函数表vtbl(virtual function table),这张表实际上是一个函数指针的数组,记录了虚函数的入口地址。只要这个类有虚函数,不管是自己定义的还是从父类继承过来的,那么类的每个实例---对象都有一个指针vptr(virtual function table pointer),它指向类的虚函数表。

虚函数(多态)机制的三个条件:

1.派生关系

2.virtual 属性

3.指针-->访问方式

//---------------------------------------------------------------------------------------

Q:有12个小球,外形相同,其中一个小球的质量与其他11个不同,给一个天平,问如何用3次把这个小球找出来并且求出这个小球是比其他的轻还是重?

A:

将12个球分别编号为a1,a2,a3.......a10,a11,a12.

第一步:将12球分开3拨,每拨4个,a1~a4第一拨,记为b1, a5~a8第2拨,记为b2,其余第3拨,记为b3;

第二步:将b1和b2放到天平两盘上,记左盘为c1,右为c2;这时候分两中情况:

1.c1和c2平衡,此时可以确定从a1到a8都是常球;然后把c2拿空,并从c1上拿下a4,从a9到a12四球里随便取三球,假设为a9到a11,放到c2上。此时c1上是a1到a3,c2上是a9到a11。从这里又分三种情况:

A:天平平衡,很简单,说明没有放上去的a12就是异球,而到此步一共称了两次,所以将a12随便跟11个常球再称一次,也就是第三次,马上就可以确定a12是重还是轻;

B:若c1上升,则这次称说明异球为a9到a11三球中的一个,而且是比常球重。取下c1所有的球,并将a8放到c1上,将a9取下,比较a8和a11(第三次称),如果平衡则说明从c2上取下的a9是偏重异球,如果不平衡,则偏向哪盘则哪盘里放的就是偏重异球;

C:若c1下降,说明a9到a11里有一个是偏轻异球。次种情况和B类似,所以接下来的步骤照搬B就是;

2.c1和c2不平衡,这时候又分两种情况,c1上升和c1下降,但是不管哪种情况都能说明a9到a12是常球。这步是解题的关键。也是这个题最妙的地方。

A:c1上升,此时不能判断异球在哪盘也不能判断是轻还是重。取下c1中的a2到a4三球放一边,将c2中的a5和a6放到c1上,然后将常球a9放到c2上。至此,c1上是a1,a5和a6,c2上是a7,a8和a9。此时又分三中情况:

1)如果平衡,说明天平上所有的球都是常球,异球在从c1上取下a2到a4中。而且可以断定异球轻重。因为a5到a8都是常球,而第2次称的时候c1是上升的,所以a2到a4里必然有一个轻球。那么第三次称就用来从a2到a4中找到轻球。这很简单,随便拿两球放到c1和c2,平衡则剩余的为要找球,不平衡则哪边低则哪个为要找球;

2)c1仍然保持上升,则说明要么a1是要找的轻球,要么a7和a8两球中有一个是重球(这步懂吧?好好想想,很简单的。因为a9是常球,而取下的a2到a4肯定也是常球,还可以推出换盘放置的a5和a6也是常球。所以要么a1轻,要么a7或a8重)。至此,还剩一次称的机会。只需把a7和a8放上两盘,平衡则说明a1是要找的偏轻异球,如果不平衡,则哪边高说明哪个是偏重异球;

3)如果换球称第2次后天平平衡打破,并且c1降低了,这说明异球肯定在换过来的a5和a6两求中,并且异球偏重,否则天平要么平衡要么保持c1上升。确定要找球是偏重之后,将a5和a6放到两盘上称第3次根据哪边高可以判定a5和a6哪个是重球;

B:第1次称后c1是下降的,此时可以将c1看成c2,其实以后的步骤都同A,所以就不必要再重复叙述了。至此,不管情况如何,用且只用三次就能称出12个外观手感一模一样的小球中有质量不同于其他11球的偏常的球。而且在称的过程中可以判定其是偏轻还是偏重。

Q:是不是一个父类写了一个virtual函数,如果子类覆盖它的函数不加virtual,也能实现多态?

A:

virtual修饰符会被隐形继承的。virtual可加可不加,子类的空间里面有父类的所有变量(static除外),同一个函数只存在一个实体(inline除外),子类覆盖它的函数不加virtual,也能实现多态。

------------------------------------------------------------------------------------------

Q:输入一个字符串,将其逆序后输出。(使用C++,不建议用伪码)

A:

#include <iostream>

#include <string>

using namespace std;

int main()

{

char * src = "hello world";

int len = 0;

char * dest = new char;

while( *src++ != NULL )

{

cout<<*(src-1);

}

src -= 2;

cout<<endl;

while( *src-- != NULL )

{

*dest = *(src+1);

cout<<*dest;

*dest++;

}

cout<<endl;

return 0;

}

------------------------------------------------------------------------------------------

Q:写出程序结果:

void Func(char str[100])

{

printf("%d/n", sizeof(str));

}

A: 4

分析: 指针长度

------------------------------------------------------------------------------------------

Q:请简单描述Windows内存管理的方法?

A:windows内存管理主要处理两件事情:

一.把那些不常用的程序片段放入虚拟内存,当需要用到的时候load入主存中。

二.计算程序片段在主存的物理位置,以便cpu调用。

内存管理分为块式管理,页式管理,段式管理,段页式管理。

块式管理:把主存分为一大块,一大块的,当所需的程序片段不在主存时,就分配一块主存空间,把程序片段load入主存,就算所需的程序片段只有几个字节也只能把这一块分配给它。这样会造成很大的浪费,平均浪费了50%的内存空间,但是易于管理。

页式管理:把主存分成一页一页的 ,每一页的空间要比一块一块的空间小得很多,显然这种方法空间的利用率要比块式管理高效很多。

段式管理:把主存分成一段一段的,每一段的空间又要比一页一页的空间小很多,这种方法在空间利用率上又比页面管理高很多,但是也存在一个缺点。一个程序片段可能会被分成十几段,这样会浪费很多时间在计算每一段物理地址上。

段页式管理:结合了段式管理和页式管理的优点。把主存分为若干页,每一页又分成若干段,这样做不但使得空间的利用率高效,而且在访问物理地址上速度也会提升。

------------------------------------------------------------------------------------------

Q:用C写一个输入的整数,倒着输出整数的函数,要求用递归方法?

A:

#include <iostream>

#include <string>

using namespace std;

void fun(int a)

{

cout<<a%10;

a /= 10;

if(a <= 0)

return;

fun( a );

}

int main()

{

int input_data;

cout<<"请输入一个整数: ";

cin>>input_data;

fun(input_data);

return 0;

}

------------------------------------------------------------------------------------------

Q:以下程序输出的结果是什么?

#include "stdafx.h"

#define SQR(X) X*X

int main(int argc, char* argv[])

{

int a = 10;

int k = 2;

int m = 1;

a /= SQR(k+m)/SQR(k+m);

printf("%d/n",a);

return 0;

}

A: 1

解释:

SQR(k+m)/SQR(k+m)

= k+m*k+m / k+m*k+m

= 2+1*2+1/2+1*2+1

= 2+2+0+2+1

= 7

a = a / 7 = 1

------------------------------------------------------------------------------------------

Q:const 符号常量;

(1)const char *p

(2)char const *p

(3)char * const p

(4)const char * const p

说明上面四种描述的区别;

A:

(1)const char *p 是指向字符型常量的指针,该指针指向的值不能变,但指针可以指向其他变量。

(2)char const *p 是指向字符型常量的指针,该指针指向的值不能变,但指针可以指向其他变量。

(3)char * const p 是指向字符型的常量指针,该指针指向的值可以改变,但是指针不能指向其他变量。

(4)const char * const p 是指向字符型常量的常量指针,该指针指向的值不能改变,指针不能指向其他变量。

可以这样记:

const 在*之"前"表示内容不变

const 在*之"后"表示指针不变

------------------------------------------------------------------------------------------

Q:下面是C语言中两种if语句判断方式。请问哪种写法更好?为什么?

int n;

if (n == 10) // 第一种判断方式

if (10 == n) // 第二种判断方式

A:第二种

如果少了一个"=",编译器会检测出错误,如果是第一种,编译器不会提示错误。

------------------------------------------------------------------------------------------

Q:下面的代码有什么问题?

void DoSomeThing(...)

{

char* p;

...

p = malloc(1024); // 分配1K的空间

if (NULL == p)

return;

...

p = realloc(p, 2048); // 空间不够,重新分配到2K

if (NULL == p)

return;

...

}

A:

p = malloc(1024); 应该写成:p = (char *) malloc(1024);

char * p = NULL; 要初始化。

“栈内存”的指针在return结束的时候自动消亡,但是并不意味着释放了P的内存空间,容易造成内存泄漏。

------------------------------------------------------------------------------------------

Q:请填写BOOL,float,指针变量与“零值”比较的if语句。

提示:这里“零值”可以是0,0.0,false或者“空指针”。例如int变量n与“零值”比较的if语句为:

if( n == 0 )

if( n != 0 )

以此类推。

请写出BOOL flag与“零值”比较的if语句:

请写出float x与“零值”比较的if语句:

请写出char *p与“零值”比较的if语句:

A:

请写出BOOL flag与“零值”比较的if语句:

if( flag )

if( !flag )

如下写法均属不良风格,不得分

if( flag == true )

if( flag == 1 )

if( flag == false )

if( flag == 0 )

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

请写出float x与“零值”比较的if语句:

const float epsinon = 0.00001

if(( x >= -epsinon )&&( x <= epsinon ))

如下是错误的写法,不得分

if( x == 0.0 )

if( x != 0.0 )

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

请写出char *p与“零值”比较的if语句:

if( p == NULL )

if( p != NULL )

如下写法均属不良风格,不得分

if( p == 0 )

if( p != 0 )

if(p)

if(!)

------------------------------------------------------------------------------------------

Q:以下为windows NT下的32位C++程序,请计算sizeof的值。

char str[] = "Hello";

char *p = str;

int n =10;

请计算

sizeof(str) =

sizeof(p) =

sizeof(n) =

void Func(char str[100])

{

请计算

sizeof(str) =

}

void *p = malloc(100);

请计算

sizeof(p) =

A:

char str[] = "Hello";

char *p = str;

int n =10;

请计算

sizeof(str) = 6;

sizeof(p) = 4;

sizeof(n) = 4;

void Func(char str[100])

{

请计算

sizeof(str) = 4;

}

void *p = malloc(100);

请计算

sizeof(p) = 4;

------------------------------------------------------------------------------------------

Q:头文件中的ifdef/define/endif干什么用?

A:预编译指令,防止该头文件被重复引用。

------------------------------------------------------------------------------------------

Q:#include <filename.h> 和 #include "filename.h" 有什么区别?

A:

对于#include <filename.h>,编译器从标准库路径开始搜索filename.h。

对于#include "filename.h" ,编译器从用户的工作路径开始搜索filename.h。

------------------------------------------------------------------------------------------

Q:const有什么用途?(请至少说明两种)

A:

1.可以定义const常量。

2.const可以修饰函数的参数,返回值,甚至函数的定义体。被const修饰的东西都受到强烈的保护,可以预防意外的变动,能提高程序的健壮性。

------------------------------------------------------------------------------------------

Q:在C++程序中调用被C编译器编译后的函数,为什么要加extern"C"声明?

A:

C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。

假设某个函数函数的原型为:void foo(int x, int y);

该函数在C编译器编译后的库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。

C++提供了C连接交换指定符号extern"C"来解决名字匹配问题。

------------------------------------------------------------------------------------------

Q:写出运行结果:

int main()

{

char str[] = "world"; cout << sizeof(str) << ": ";

char *p = str; cout << sizeof(p) << ": ";

char i = 10; cout << sizeof(i) << ": ";

void *pp = malloc(10); cout << sizeof(p) << endl;

}

A:

char str[] = "world"; cout << sizeof(str) << ": "; 6

char *p = str; cout << sizeof(p) << ": "; 4

char i = 10; cout << sizeof(i) << ": "; 1

void *pp = malloc(10); cout << sizeof(p) << endl; 4
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  职场 程序员 休闲