c++ 面试题

来源:互联网 发布:开淘宝网店怎样发货 编辑:程序博客网 时间:2024/05/16 12:35

strcpy函数:注意由于字符串数组长度的问题带来内存访问越界,注意'\0'的问题

写出完整版的strcpy函数:

先给出我第一直觉写的,简直惨不忍睹:

[cpp] view plain copy
  1. void strcpy(char*s1, char* s2)  
  2. {  
  3.     assert(s1==NULL || s2==NULL);  
  4.     int i=0;  
  5.     for(i=0;i<=strlen(s2);i++)  
  6.     {  
  7.         s1[i] = s2[i];  
  8.     }  
  9. }  

问题:1 输入变量修饰const  2 源和目的地址添加断言 3 为了实现链式操作,返回目的地址

正确的答案应该是:ps,strcpy将空字符也会拷贝'\0'

[cpp] view plain copy
  1. char * strcpy(char* pDst,char* pSrc)  
  2. {  
  3.     assert((pDst!=NULL)&&(pSrc!=NULL));  
  4.     char *pAddress=pDst;  
  5.     while((*pDst++ = *pSrc++)!='\0');  
  6.     return pAddress;  
  7. }  
写出string类的拷贝函数、赋值函数、析构函数,给出string的原型如下:

[cpp] view plain copy
  1. class String  
  2. {   
  3.  public:   
  4.  String(const char *str = NULL); // 普通构造函数   
  5.  String(const String &other); // 拷贝构造函数   
  6.  ~ String(void); // 析构函数   
  7.  String & operator =(const String &other); // 赋值函数   
  8.  private:   
  9.  char *m_data; // 用于保存字符串   
  10. };  

答案:

[cpp] view plain copy
  1. //总之对于任何程序,注意几点  
  2. //注意输入,比如加const  
  3. //注意NULL,对于指针变量,对于new的动态内存,对于assert都与NULL相关  
  4. //注意返回值  
  5.   
  6. String::String(const char* str=NULL)//普通构造函数  
  7. {     
  8.     if(str==NULL)  
  9.     {  
  10.         m_data=new char[1];  
  11.         assert(m_data!=NULL);//养成在分配内存后的检查行为  
  12.         *m_data='\0';  
  13.     }  
  14.     else  
  15.     {  
  16.         m_data=new char[strlen(str)+1];  
  17.         assert(m_data!=NULL);//养成在分配内存后的检查行为  
  18.         strcpy(m_data,str);  
  19.     }  
  20. }  
  21.   
  22. String::String(const String& other)//拷贝构造函数  
  23. {  
  24.     m_data=new char[strlen(other.m_data)+1];  
  25.     assert(m_data!=NULL);  
  26.     strcpy(m_data,other.m_data);  
  27. }  
  28.   
  29. //记住赋值函数三部曲  
  30. //1 检查是否是自赋值  
  31. //2 销毁动态内存  
  32. //3 返回自身引用  
  33. String& String::operator=(const String& other)//赋值函数  
  34. {  
  35.     //赋值函数,都要有检查自赋值的行为  
  36.     if(this==&other) return *this;  
  37.       
  38.     if(m_data!=NULL) delete [] m_data;  
  39.     m_data=new char[strlen(other.m_data)+1];  
  40.     assert(m_data!=NULL);//养成在分配内存后的检查行为  
  41.     strcpy(m_data,other.m_data);  
  42.     return *this;//赋值函数要返回自身,才能支持链式操作  
  43. }  
  44.   
  45. String::~String()//析构函数  
  46. {  
  47.     delete [] m_data;  
  48. }  

4 strlen()返回的是字符串数组中字符的个数,不包括最后的空字符'\0'

指出static和const关键字尽可能多的作用:

【解答】 
static关键字至少有下列n个作用:   
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;   
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;   
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;   
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;   
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。    
const关键字至少有下列n个作用:   
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;   
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;   
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;   
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的 成员变量;   
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如:   
const classA operator*(const classA& a1,const classA& a2);   
operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错:   
classA a, b, c;   
(a * b) = c; // 对a*b的结果赋值   
操作(a * b) = c显然不符合编程者的初衷,也没有任何意义。  

字节序,大小端

字节序,顾名思义字节的顺序,再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。其实大部分人在实际的开发中都很少会直接和字节序打交道。唯有在跨平台以及网络程序中字节序才是一个应该被考虑的问题。
在所有的介绍字节序的文章中都会提到字节序分为两类:Big-Endian和Little-Endian,引用标准的Big-Endian和Little-Endian的定义如下:
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
c) 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。 

ps:我们的pc,x86架构的是小端模式

7 正负数的表示:

假设这也是一个int类型,那么: 
1、先取-1的原码:10000000 00000000 00000000 00000001 
2、得反码: 11111111 11111111 11111111 11111110(除符号位按位取反) 
3、得补码: 11111111 11111111 11111111 11111111 
可见,-1在计算机里用二进制表达就是全1。16进制为:0xFFFFFF 
主要知识点: 
①正数的反码和补码都与原码相同。 
②而负数的反码为对该数的原码除符号位外各位取反。 
③负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1 

原创粉丝点击