c++那几张比较难
2014-06-26 21:41:17 Froser 阅读数 1468

  由于C++已经遗忘得差不多了,我翻起了最新初版的C++ Primer,打算深入了解一下C++这一门语言。C++ Primer第五版可谓是“重构”过的,融合了C++11的标准,并将它们全部在书中列举了出来。

  在学习的过程中,我会把C++与Java、C#等纯面向对象的语言进行对比,中间的一些感悟,仅仅代表个人的意见,其中有对有错,也可能会存在一些争议。

  差不多翻完了整本Primer C++,并了解完C++11标准后,我有了如下感慨:C++是一门灵活、强大、效率低下的语言。

  所谓的“灵活”、“强大”,是指与Java、C#相比,而“效率低下”是指相对于C#、Java的开发效率,而不是程序的运行效率。同时,C++“约定俗成”了许多规则,这些规则难以全部记下来,因此在编程的时候手边最好有一本C++的手册。

  我列举几个C++灵活的地方:

  1、操作符重载,拷贝控制,隐式转换等

  在C++中,几乎所有的操作都可以被重载,例如+、-、new、delete等,哪怕你使用=赋值,其实都是在运行一个函数。如果你没有定义这样的函数,则编译器会使用它的合成版本(也就是默认版本)。默认版本的拷贝其实就是把成员的值拷贝,如果成员是一个指针,则仅仅拷贝地址。举例说明,如果有一个A类的实例a,成员中含有一个指针ptr,当用默认版本进行拷贝后,如A b = a;,那么b和a中的ptr指向的是同一个地址,如果a、b其中之一,ptr所指向的对象被析构了,那么当析构另外一个对象的时候就会发生错误(C++ Primer 第五版,P447),所以,需要析构的对象也需要一个拷贝和赋值的操作。

  上述的例子说明了,作为类的设计者,你必须要把所有的情况考虑清楚,要对它的内存分配了如指掌,否则你设计出来的类很可能会有问题。

  另一个例子是隐式转换,诸如std::string str = "hello",它把C风格的const char*转换为了std::string,这种转换在我们的理解中是很直接的,但是有时候,这种转换不仅难以理解,还会造成二义性导致编译无法通过。

  在我看来,操作符的重载对于一门语言不是必要的。在C++中我们可以轻易地想到两个std::string相加相当于连接两个字符串,而在Java、C#中,是禁止重载运算符的(C#中有个例外,就是它默认重载了String类的+),原因我猜想可能是防止程序结构太过于混乱。事实上,我是不太习惯于重载过多运算符,除非必须要重载(例如使用map类时,必须要重载<),因为它确实会增加阅读代码的难度。举例说明,我想在C++和C#(或Java)中分别构造一个类,它们拥有“加法”运算符,在C++中可能是这样:

class CanAdd{
public:
    int value;
    CanAdd& operator + (const CanAdd a){
        value += a.value; return *this;
    }
};

  对于某些需要用到+运算的模板类,将这个类传入模板类中显然是没有问题的,但是模板类并不能保证传入的类一定有+运算符。在C#或Java中,我们更喜欢这样(Java代码):

abstract class ICanAdd{
	int value;
	abstract ICanAdd add(ICanAdd item);
}

class CanAdd extends ICanAdd{
	public ICanAdd add(ICanAdd item){
		value += item.value;
		return this;
	}
}

  抽象类ICanAdd中明确包含了add方法,那么所有的ICanAdd类型的对象,都是可以调用add的,至于调用怎样的add由它们的基类决定。在C#、Java中,这种类型运用在泛型中是很安全的,因为我们可以约束这个泛型类一定要继承ICanAdd,从而保证它一定能够调用add,而模板类就不能这样保证了,编译器发现问题只有在模板实例化那一刻才知道,那么,如果有问题,面临着的可能是一大堆链接错误。

  另外,过分使用重载符的意义是比较含糊的,例如std::cout << std::endl;,cout是std命名空间的一个成员,但是endl却是std中的一个函数,我个人认为如果一个程序中充斥着这样的“约定俗成”的运算符,会过于难以理解。

  2、指针、值、引用及多态性

  C++的困难之处在于它的内存管理。在C#和Java中,有完善的垃圾回收机制,除了基本类型(以及C#中的struct),传递的方式都是引用(C#中也可以将一个值类型变量来引用传递)。不同的符号,如*、&在不同的位置有不同的含义,而且是很容易混淆的。例如:instance*t,它到底是表示instance乘以t,还是表示一个指向instance类的指针t呢。这一点在模板中尤为明显,对于包含域运算符的类型,一定要加上typename,例如typename CLASS<T>::member,因为编译器不知道member是一个类型还是一个成员变量。

  左值引用、右值引用、值传递、引用传递是对编程人员提出的大挑战,当我们用decltype、auto、const等关键字时尤为明显。例如有语句int a,则decltype(a)返回的类型是int,而decltype((a))返回的类型是int&,这些规则,只能在实战中慢慢记忆。

  C++在定义变量的时候,和C#、Java不同。例如已经定义好了一个类A,在C++中,A a;表示,a已经被定义(已经被分配好了空间),如果你只想声明它,要么是extern A a;,要么就是A* a;。在C#、Java中,A a;永远是声明,除非你用了A a = new A(),表示a已经被实例化。使用未被实例化的变量会引发异常。

  C++虽然是一门“面向对象”的语言,但是我们却不能直接进行“面向对象”来操作它。举例如下:

#include <iostream>
using namespace std;

class Base {
public:
    virtual void Call(){
        std::cout << "Base func called" << std::endl;
    }
};

class Derived : public Base {
public:
    void Call(){
        std::cout << "Derived func called" << std::endl;
    }
};

void call(Base b){
    b.Call();
}

int main(int argc, const char * argv[])
{
    Base base;
    Derived derived;
    call(base);
    call(derived);
    return 0;
}
  程序运行的结果:

Base func called
Base fund called

  根据多态的原则,call函数调用了成员函数Call,为什么对于derived对象,仍然调用的是基类的Call呢?原因是,C++的多态性只体现在引用和指针上:当你传入一个derived给call时,其实编译器是按照Base的拷贝构造函数拷贝了一个参数b,则b的类型是Base,那么再调用b.Call(),调用的肯定是Base.Call了。为了防止Base调用拷贝构造函数,我们给call传的参数,要么是Base&,要么是Base*。如果我们要使用“多态”,那么对象必须是引用或指针,因为给它们赋值不会触发拷贝构造。

  3、接口与多重继承

  C++中没有接口的概念,但是有继承的概念。继承是面向对象编程中的一大特点。C++支持多重继承,也支持各种访问权限的继承;C#、Java不支持多重继承,它们只能继承于一个类,但是可以继承多个接口。C++支持多重继承的原因我想其中之一是因为C++中没有“接口”的概念。接口是一个完全抽象的类,它只声明了函数体,不能实现它们。C++中可以用抽象类来实现接口,因此,C++必须要支持多重继承。例如,一只小狗,它可以跑,可以吃东西,它是一只动物,那么在C++中,可以这样声明:class Dog : public Animal, public CanEat, public CanRun,而在Java中,则是这样声明:class Dog extends Animal implements CanEat, CanRun,且CanEat,CanRun必须为interface——它们不能实现自己的成员函数,只能声明。
  多重继承会带来一些麻烦,比方说父类们都继承了同一个类,那么此派生类会继承那个类两次,此时就要用虚基类来解决问题,另外,多重继承也会出现一些重名的问题。把“接口”从类中分离出来是有好处的,它清楚地说明了类中一定会存在的方法,如果用一个纯抽象类来代替接口,则可能会出现“Is a”这样的混淆,即——Dog是Animal,并且同时是CanEat, CanRun这样的混淆,而正确的看法应该是:Dog是animal,且存在CanEat、CanRun这样的能力。
  因此到现在,我都有个习惯,一个类最多继承一个包含了成员或实现多个成员函数的类,并且可以继承多个纯抽象类(不包含成员字段,且仅包含成员函数的声明的类)。当然,这种习惯可能在某些情况下是有局限性的。

  4、typedef和#define

  先说说define吧。宏定义是提高程序效率的一种有效手段,因为它的时间消耗在了编译器。我们可以把很多常用的函数写成宏定义,这样运行它的时候参数就不会反复出栈入栈影响效率了,C++中也可以把函数定义成inline来提高效率。define在一定程度上可以提高代码的可读性,但是漫天的define会让人疑惑。因此,在C#中define的功能被做了限制,即define不能定义一个宏为一个值,它仅仅只能定义,以及判断它是否定义了,最常见的用途就是#define DEBUG,来进行某些调试。
  typedef,以及C++11中常用的using,是给类型命别名的。它主要的作用,在我看来有两个:一是提高代码的可读性,例如,一个string类型的可读性肯定比const char*高,一个strVectorWithVector的可读性肯定比vector<vector<std::string> >高,同define一样,漫天的typedef同样会降低代码的可读性。第二个作用是增加软件的可移植性。在机器A上,int占8个自己,B机器上,int占16个字节,那么在A机器上定义的int a可能在B机器上都要改成long a,这样的工作量巨大而且容易出错。因此,在A机器上,用typedef将int命名为MyInt,在B机器上,将MyInt对应的类型改成long就实现了所有类型的改变。
  不过,这样的类型移植在C#和Java上应该出现得很少的,因为它们都有各自的“虚拟机”——.NET库有CLR,Java有Java虚拟机,它们在不同的终端上会处理这样的兼容性问题的。

  5、内存管理

  内存管理是C++程序员的噩梦,虽然标准库引入了boost中的shared_ptr,但是它仍然没有一个垃圾回收机制,shared_ptr使用起来也有一定难度,不像“垃圾回收”那样可以无脑使用,C++的设计者可能认为程序的所有控制权应该交给程序员,但是不是所有的程序员(或他们的老板)都是那么有耐心,一个完善的内存管理机制可能需要花费相当大的时间。ObjectiveC引入了autorelease垃圾回收机制,但我认为C++在下一次标准出来之前也不会有垃圾回收机制。
  在C#和Java中,一个类的回收是不定时的,但是你可以定义它们在回收时应该要做些什么,而在C++中,析构神马的,都要自己写。

  以上列举了几点C++十分灵活的地方,它灵活的地方还有许多,如迭代器——C++中,如果要使用range for,则这个类必须拥有begin(),end(),它们返回一个迭代器,这个迭代器可以是自己定义的一个类,它必须实现解引用*运算符、!=运算符和++运算符。标准库中提供了各种各样复杂的迭代器,而在range for出来之前,QT中已经实现了foreach“语句”。在C#、Java中,如果要使用foreach,类必须要实现迭代器接口。
  C++没有“程序集”的概念,所以也就不存在反射机制,能够使用decltype已经算是一种“突破”了。C++中,一个对象即一块内存,在C#、Java中,我们可以用GetType或.class方法来获取类型的信息。

  不得不说,C++中有很多“人为规定”,大部分操作、内存管理需要自己实现,对计算机的结构需要有很清晰地了解才能写出好的程序。C++如此复杂,征服它会不会很有成就感!
2010-08-03 22:24:00 wzm012 阅读数 3772

1.指针的引用类,就是把指针和引用计数打包成了一个类,这样便于指针的回收,一种很好的内存管理模式

虽然理解其原理,但是具体如何实现,并且运行的,还是比较晕,这点上看出java的好处了

核心的类是RefCounted<>这个模板类,注意这个类使用了一个阻止代码扩展的技术,叫HOSTING

其他涉及的模板类都带有Ptr<>,如PassPtr<>,RefPtr<>等

 

2.RTTI技术,webkit的继承关系很复杂,dom有一套,html有一套,render有一套,js有一套,css有一套

并且它们不是孤立的,互相之间是有很强的联系的,

因此大量的virtual函数的使用,让人要想找到真正的调用,有时需要gdb才可以。

但是网上都说webkit的代码结构是最整洁的,没看过其他的不好下结论,

从看webkit的代码,再加上这句话,只能说一句,做浏览器很不容易呀

 

3.c++的STL库,都说这个库很经典很简单,可惜还没有真正地用过。

比较常用的是vector,hash,map等

 

。。。

2007-04-04 20:04:00 thimin 阅读数 7479
动态内存分配(Dynamic memory allocation)


14. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?

这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(主要是 P.J. Plauger, 他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:下面的代码片段的输出是什么,为什么?

char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");

这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是“Got a valid pointer”。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。

Typedef

15. Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;

以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;

第一个扩展为
struct s * p1, p2;

上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。

晦涩的语法

16. C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;

这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:
c = a++ + b;
因此, 这段代码持行后a = 6, b = 7, c = 12。
如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题

What will print out?

main()
{
char *p1=“name”;
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
while(*p2++ = *p1++);
printf(“%sn”,p2);

}

Answer:empty string.

What will be printed as the result of the operation below:

main()
{
int x=20,y=35;
x=y++ + x++;
y= ++y + ++x;
printf(“%d%dn”,x,y);
}

Answer : 5794

What will be printed as the result of the operation below:

main()
{
int x=5;
printf(“%d,%d,%dn”,x,x< <2,x>>2);
}

Answer: 5,20,1

What will be printed as the result of the operation below:

#define swap(a,b) a=a+b;b=a-b;a=a-b;
void main()
{
int x=5, y=10;
swap (x,y);
printf(“%d %dn”,x,y);
swap2(x,y);
printf(“%d %dn”,x,y);
}

int swap2(int a, int b)
{
int temp;
temp=a;
b=a;
a=temp;
return 0;

}

Answer: 10, 5
10, 5

What will be printed as the result of the operation below:

main()
{
char *ptr = ” Cisco Systems”;
*ptr++; printf(“%sn”,ptr);
ptr++;
printf(“%sn”,ptr);
}

Answer:Cisco Systems
isco systems

What will be printed as the result of the operation below:

main()
{
char s1[]=“Cisco”;
char s2[]= “systems”;
printf(“%s”,s1);
}
Answer: Cisco

What will be printed as the result of the operation below:

main()
{
char *p1;
char *p2;
p1=(char *)malloc(25);
p2=(char *)malloc(25);

strcpy(p1,”Cisco”);
strcpy(p2,“systems”);
strcat(p1,p2);

printf(“%s”,p1);

}

Answer: Ciscosystems

The following variable is available in file1.c, who can access it?:

static int average;

Answer: all the functions in the file1.c can access the variable.

WHat will be the result of the following code?

#define TRUE 0 // some code
while(TRUE)
{

// some code

}

Answer: This will not go into the loop as TRUE is defined as 0.

What will be printed as the result of the operation below:

int x;
int modifyvalue()
{
return(x+=10);
}
int changevalue(int x)
{
return(x+=1);
}

void main()
{
int x=10;
x++;
changevalue(x);
x++;
modifyvalue();
printf("First output:%dn",x);

x++;
changevalue(x);
printf("Second output:%dn",x);
modifyvalue();
printf("Third output:%dn",x);

}

Answer: 12 , 13 , 13

What will be printed as the result of the operation below:

main()
{
int x=10, y=15;
x = x++;
y = ++y;
printf(“%d %dn”,x,y);
}

Answer: 11, 16

What will be printed as the result of the operation below:

main()
{
int a=0;
if(a==0)
printf(“Cisco Systemsn”);
printf(“Cisco Systemsn”);
}

Answer: Two lines with “Cisco Systems” will be printed.



再次更新C++相关题集

1. 以下三条输出语句分别输出什么?[C易]
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
cout << boolalpha << ( str1==str2 ) << endl; // 输出什么?
cout << boolalpha << ( str3==str4 ) << endl; // 输出什么?
cout << boolalpha << ( str5==str6 ) << endl; // 输出什么?

13. 非C++内建型别 A 和 B,在哪几种情况下B能隐式转化为A?[C++中等]
答:
a. class B : public A { ……} // B公有继承自A,可以是间接继承的
b. class B { operator A( ); } // B实现了隐式转化为A的转化
c. class A { A( const B& ); } // A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数
d. A& operator= ( const A& ); // 赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个

12. 以下代码中的两个sizeof用法有问题吗?[C易]
void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母
{
for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
if( 'a'<=str[i] && str[i]<='z' )
str[i] -= ('a'-'A' );
}
char str[] = "aBcDe";
cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;

7. 以下代码有什么问题?[C难]
void char2Hex( char c ) // 将字符以16进制表示
{
char ch = c/0x10 + '0'; if( ch > '9' ) ch += ('A'-'9'-1);
char cl = c%0x10 + '0'; if( cl > '9' ) cl += ('A'-'9'-1);
cout << ch << cl << ' ';
}
char str[] = "I love 中国";
for( size_t i=0; i<strlen(str); ++i )
char2Hex( str[i] );
cout << endl;

4. 以下代码有什么问题?[C++易]
struct Test
{
Test( int ) {}
Test() {}
void fun() {}
};
void main( void )
{
Test a(1);
a.fun();
Test b();
b.fun();
}

5. 以下代码有什么问题?[C++易]
cout << (true?1:"1") << endl;

8. 以下代码能够编译通过吗,为什么?[C++易]
unsigned int const size1 = 2;
char str1[ size1 ];
unsigned int temp = 0;
cin >> temp;
unsigned int const size2 = temp;
char str2[ size2 ];

9. 以下代码中的输出语句输出0吗,为什么?[C++易]
struct CLS
{
int m_i;
CLS( int i ) : m_i(i) {}
CLS()
{
CLS(0);
}
};
CLS obj;
cout << obj.m_i << endl;

10. C++中的空类,默认产生哪些类成员函数?[C++易]
答:
class Empty
{
public:
Empty(); // 缺省构造函数
Empty( const Empty& ); // 拷贝构造函数
~Empty(); // 析构函数
Empty& operator=( const Empty& ); // 赋值运算符
Empty* operator&(); // 取址运算符
const Empty* operator&() const; // 取址运算符 const
};

3. 以下两条输出语句分别输出什么?[C++难]
float a = 1.0f;
cout << (int)a << endl;
cout << (int&)a << endl;
cout << boolalpha << ( (int)a == (int&)a ) << endl; // 输出什么?
float b = 0.0f;
cout << (int)b << endl;
cout << (int&)b << endl;
cout << boolalpha << ( (int)b == (int&)b ) << endl; // 输出什么?

2. 以下反向遍历array数组的方法有什么错误?[STL易]
vector array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 3 );

for( vector::size_type i=array.size()-1; i>=0; --i ) // 反向遍历array数组
{
cout << array[i] << endl;
}

6. 以下代码有什么问题?[STL易]
typedef vector IntArray;
IntArray array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 2 );
array.push_back( 3 );
// 删除array数组中所有的2
for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor )
{
if( 2 == *itor ) array.erase( itor );
}

11. 写一个函数,完成内存之间的拷贝。[考虑问题是否全面]
答:
程序代码 程序代码
void* mymemcpy( void *dest, const void *src, size_t count )
{
char* pdest = static_cast<char*>( dest );
const char* psrc = static_cast<const char*>( src );
if( pdest>psrc && pdest<psrc+cout ) 能考虑到这种情况就行了
{
for( size_t i=count-1; i!=-1; --i )
pdest[i] = psrc[i];
}
else
{
for( size_t i=0; i<count; ++i )
pdest[i] = psrc[i];
}
return dest;
}
int main( void )
{
char str[] = "0123456789";
mymemcpy( str+1, str+0, 9 );
cout << str << endl;

system( "Pause" );
return 0;
}

2018-07-05 18:02:39 CHCH998 阅读数 168
原文地址为:较难一些的C/C++面试题目

动态内存分配(Dynamic memory allocation)


14. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?

这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(主要是 P.J. Plauger, 他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:下面的代码片段的输出是什么,为什么?

char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");

这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是“Got a valid pointer”。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。

Typedef

15. Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;

以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;

第一个扩展为
struct s * p1, p2;

上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。

晦涩的语法

16. C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;

这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:
c = a++ + b;
因此, 这段代码持行后a = 6, b = 7, c = 12。
如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题

What will print out?

main()
{
char *p1=“name”;
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
while(*p2++ = *p1++);
printf(“%sn”,p2);

}

Answer:empty string.

What will be printed as the result of the operation below:

main()
{
int x=20,y=35;
x=y++ + x++;
y= ++y + ++x;
printf(“%d%dn”,x,y);
}

Answer : 5794

What will be printed as the result of the operation below:

main()
{
int x=5;
printf(“%d,%d,%dn”,x,x< <2,x>>2);
}

Answer: 5,20,1

What will be printed as the result of the operation below:

#define swap(a,b) a=a+b;b=a-b;a=a-b;
void main()
{
int x=5, y=10;
swap (x,y);
printf(“%d %dn”,x,y);
swap2(x,y);
printf(“%d %dn”,x,y);
}

int swap2(int a, int b)
{
int temp;
temp=a;
b=a;
a=temp;
return 0;

}

Answer: 10, 5
10, 5

What will be printed as the result of the operation below:

main()
{
char *ptr = ” Cisco Systems”;
*ptr++; printf(“%sn”,ptr);
ptr++;
printf(“%sn”,ptr);
}

Answer:Cisco Systems
isco systems

What will be printed as the result of the operation below:

main()
{
char s1[]=“Cisco”;
char s2[]= “systems”;
printf(“%s”,s1);
}
Answer: Cisco

What will be printed as the result of the operation below:

main()
{
char *p1;
char *p2;
p1=(char *)malloc(25);
p2=(char *)malloc(25);

strcpy(p1,”Cisco”);
strcpy(p2,“systems”);
strcat(p1,p2);

printf(“%s”,p1);

}

Answer: Ciscosystems

The following variable is available in file1.c, who can access it?:

static int average;

Answer: all the functions in the file1.c can access the variable.

WHat will be the result of the following code?

#define TRUE 0 // some code
while(TRUE)
{

// some code

}

Answer: This will not go into the loop as TRUE is defined as 0.

What will be printed as the result of the operation below:

int x;
int modifyvalue()
{
return(x+=10);
}
int changevalue(int x)
{
return(x+=1);
}

void main()
{
int x=10;
x++;
changevalue(x);
x++;
modifyvalue();
printf("First output:%dn",x);

x++;
changevalue(x);
printf("Second output:%dn",x);
modifyvalue();
printf("Third output:%dn",x);

}

Answer: 12 , 13 , 13

What will be printed as the result of the operation below:

main()
{
int x=10, y=15;
x = x++;
y = ++y;
printf(“%d %dn”,x,y);
}

Answer: 11, 16

What will be printed as the result of the operation below:

main()
{
int a=0;
if(a==0)
printf(“Cisco Systemsn”);
printf(“Cisco Systemsn”);
}

Answer: Two lines with “Cisco Systems” will be printed.



再次更新C++相关题集

1. 以下三条输出语句分别输出什么?[C易]
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
cout << boolalpha << ( str1==str2 ) << endl; // 输出什么?
cout << boolalpha << ( str3==str4 ) << endl; // 输出什么?
cout << boolalpha << ( str5==str6 ) << endl; // 输出什么?

13. 非C++内建型别 A 和 B,在哪几种情况下B能隐式转化为A?[C++中等]
答:
a. class B : public A { ……} // B公有继承自A,可以是间接继承的
b. class B { operator A( ); } // B实现了隐式转化为A的转化
c. class A { A( const B& ); } // A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数
d. A& operator= ( const A& ); // 赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个

12. 以下代码中的两个sizeof用法有问题吗?[C易]
void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母
{
for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
if( 'a'<=str[i] && str[i]<='z' )
str[i] -= ('a'-'A' );
}
char str[] = "aBcDe";
cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;

7. 以下代码有什么问题?[C难]
void char2Hex( char c ) // 将字符以16进制表示
{
char ch = c/0x10 + '0'; if( ch > '9' ) ch += ('A'-'9'-1);
char cl = c%0x10 + '0'; if( cl > '9' ) cl += ('A'-'9'-1);
cout << ch << cl << ' ';
}
char str[] = "I love 中国";
for( size_t i=0; i<strlen(str); ++i )
char2Hex( str[i] );
cout << endl;

4. 以下代码有什么问题?[C++易]
struct Test
{
Test( int ) {}
Test() {}
void fun() {}
};
void main( void )
{
Test a(1);
a.fun();
Test b();
b.fun();
}

5. 以下代码有什么问题?[C++易]
cout << (true?1:"1") << endl;

8. 以下代码能够编译通过吗,为什么?[C++易]
unsigned int const size1 = 2;
char str1[ size1 ];
unsigned int temp = 0;
cin >> temp;
unsigned int const size2 = temp;
char str2[ size2 ];

9. 以下代码中的输出语句输出0吗,为什么?[C++易]
struct CLS
{
int m_i;
CLS( int i ) : m_i(i) {}
CLS()
{
CLS(0);
}
};
CLS obj;
cout << obj.m_i << endl;

10. C++中的空类,默认产生哪些类成员函数?[C++易]
答:
class Empty
{
public:
Empty(); // 缺省构造函数
Empty( const Empty& ); // 拷贝构造函数
~Empty(); // 析构函数
Empty& operator=( const Empty& ); // 赋值运算符
Empty* operator&(); // 取址运算符
const Empty* operator&() const; // 取址运算符 const
};

3. 以下两条输出语句分别输出什么?[C++难]
float a = 1.0f;
cout << (int)a << endl;
cout << (int&)a << endl;
cout << boolalpha << ( (int)a == (int&)a ) << endl; // 输出什么?
float b = 0.0f;
cout << (int)b << endl;
cout << (int&)b << endl;
cout << boolalpha << ( (int)b == (int&)b ) << endl; // 输出什么?

2. 以下反向遍历array数组的方法有什么错误?[STL易]
vector array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 3 );<script type="text/javascript">google_ad_client = "pub-4475724770859924";google_alternate_color = "FFBBE8";google_ad_width = 468;google_ad_height = 60;google_ad_format = "468x60_as";google_ad_type = "text_image";google_ad_channel ="9379930647";google_color_border = "F8F8F8";google_color_bg = "FFFFFF";google_color_link = "FF6FCF";google_color_url = "38B63C";google_color_text = "B3B3B3";</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>

for( vector::size_type i=array.size()-1; i>=0; --i ) // 反向遍历array数组
{
cout << array[i] << endl;
}

6. 以下代码有什么问题?[STL易]
typedef vector IntArray;
IntArray array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 2 );
array.push_back( 3 );
// 删除array数组中所有的2
for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor )
{
if( 2 == *itor ) array.erase( itor );
}

11. 写一个函数,完成内存之间的拷贝。[考虑问题是否全面]
答:
程序代码 程序代码
void* mymemcpy( void *dest, const void *src, size_t count )
{
char* pdest = static_cast<char*>( dest );
const char* psrc = static_cast<const char*>( src );
if( pdest>psrc && pdest<psrc+cout ) 能考虑到这种情况就行了
{
for( size_t i=count-1; i!=-1; --i )
pdest[i] = psrc[i];
}
else
{
for( size_t i=0; i<count; ++i )
pdest[i] = psrc[i];
}
return dest;
}
int main( void )
{
char str[] = "0123456789";
mymemcpy( str+1, str+0, 9 );
cout << str << endl;

system( "Pause" );
return 0;
}


转载请注明本文地址:较难一些的C/C++面试题目
2012-12-27 16:43:49 RSwky1220 阅读数 860

  步入大学已经半年了,在这半年的时间里,我认识外面开阔的世界,认识了新的朋友、新的老师。对于我来说,我的高考是失败的。四次填报志愿失败后,我来了烟大。起初来烟台的时候,我很不适应,厌恶烟台,渐渐地我习惯了,习惯了烟台那刺骨的寒风、厚厚的积雪。

  大学的学习并不像高中老师口中所说的那样悠闲自在,每天穿梭在校园里的忙碌的身影让我回想起高中的点点滴滴。大学里我们接触到了更多更深的知识,没有了高中老师那样细致的讲解,需要靠自己的努力积累。编程专业对我来说是新鲜的、陌生的。翻开C++那厚厚的课本,看着密密麻麻的字母,我体会到了人类智慧的伟大。

  是贺老师把我们领入了深奥的C++中……

  想着刚接触C++时,每天都在想着到底怎么编,我到底哪里出错了,心里感觉挺温暖的。时间长了觉得自己慢慢地爱上了编程,喜欢上了每天对着一个程序想着自己哪里错了。在半年的C++学习中,遇到过许多拦路虎,但最后还是凭借自己的努力和别人的帮助走了过来。看着csdn博客里渐渐多起来的博文,心中五味杂陈。博客积分的增长,排名的缩减,我渐渐脱离了编程“菜鸟”的行列,这其中既有自己的努力,更重要的是贺老师不离不弃的指导。

  这一周刚刚完成了张玉老师分配的银行系统的任务,看着那300多行的代码,我好有成就感。那些代码见证了我的成长,从一开始的什么都不懂到现在的300多行的代码……经过了半年的接触,我成长了,在编程方面我在进步……

  期待下学期面向对象的程序设计,期待自己有新的进步,新的成长!奋斗

  想起高中的誓词:我为梦想而来,我为未来而战……

C#比C++慢

阅读数 993

c#通过底层的虚拟机机制减少了c/c++语言中常常容易发生的内存泄漏和安全性问题,代价是运行速度减慢。同样的由于简化了编程语言的复杂性(c#远远比c++来得简单),大大提高了开发者得效率。另外c#具有.net庞大的类库,这个优势是c++所不具有的。因此c#非常合适开发企业中处理业务的应用程序。

博文 来自: fangyi86

C++ 比心呦

阅读数 716

#includenamespaceHome{classForever_Love{private:constdoublelove=2;doubley,x,z;//Nameabbreviationpublic:voidML();};}usingnamespaceHome;intmain(){long

博文 来自: bear_love_rabbit

C++比C的优势

阅读数 2007

对于应用系统来说,用C++比用C要好

博文 来自: lotus302

C++编程——比酒量

阅读数 663

有一群海盗(不多于20人),在船上比拼酒量。过程如下:打开一瓶酒,所有在场的人平分喝下,有几个人倒下了。再打开一瓶酒平分,又有倒下的,再次重复......直到开了第4瓶酒,坐着的已经所剩无几,海盗船长也在其中。当第4瓶酒平分喝下后,大家都倒下了。等船长醒来,发现海盗船搁浅了。他在航海日志中写到:“......昨天,我正好喝了一瓶.......奉劝大家,开船不喝酒,喝酒别开船...

博文 来自: u010233287

Java和C++ 比較

阅读数 17

总体差别1.C/C++是直接执行在机器上(编译后为机器码),而java编译后产生*.class文件(字节码)是执行在java虚拟机上在(JVM),经过JVM解译(机器码)再放到真实机器上执行。JVM相当于用软件构造了一个计算机。有自己的CPU(假的),内存(也是假的)。C/C++(*.exe)-&gt;机器java(*.class)-&gt;JVM-&gt;机器这样ja...

博文 来自: weixin_33973609
没有更多推荐了,返回首页