面试题简单汇总

C++类 

已知类String的原型为:
class String
{
public:
String(const char *str = NULL);// 普通 构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operator =(const String &other);// 赋值函数
private:
char *m_data;// 用于保存字符串
};
请编写String的上述4个函数。


//普通 构造函数
String::String(const char *str)
{
if(str==NULL)
{
m_data = new char[1]; // 对空字符串自动申请存放结束标志'\0'的//加分点:对m_data加NULL 判断
*m_data = '\0';
}
else
{
int length = strlen(str);
m_data = new char[length+1]; // 若能加 NULL 判断则更好
strcpy(m_data, str);
}
}
// String的 析构函数
String::~String(void)
{
delete[] m_data; // 或delete m_data;
}
String::String(const String &other) // 输入参数为const型
{
int length = strlen(other.m_data);
m_data = new char[length+1]; //对m_data加NULL 判断
strcpy(m_data, other.m_data);
}
String & String::operator =(const String &other) // 输入参数为const
{
if(this == &other) //检查自赋值
return *this;
delete[] m_data; //释放原有的内存资源
int length = strlen( other.m_data );
m_data = new char[length+1]; //对m_data加NULL 判断
strcpy( m_data, other.m_data );
return *this; //返回本对象的引用
}


能够准确无误地编写出String类的构造函数拷贝构造函数赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!在这个类中包括了指针成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。仔细学习这个类,特别注意加注释的得分点和加分点的意义,这样就具备了60%以上的C++基本功!














1.



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为一个实际的结构,这也许不是你想要的。


第二个将struct s* 重名为一种新的类型tPS;第二个例子正确地定义了p3 和p4 两个指针。


第一个只是字符替换,第二个才是重新定义了一种新的类型




3、解释下列输出结果
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;


结果是:0 0 1 1
解答:
str1,str2,str3,str4是数组变量,它们有各自的内存空间;此时的数组名,实际上是两个分别指向数组起始元素的指针。
而str5,str6,str7,str8是指针,它们指向相同的常量区域。






4、下面的C程序是合法的吗?如果是,那么输出是什么? //Ps
#include <stdio.h>
int main()  

    int a=3, b=5;
    printf(&a["Ya!Hello! what is this? %s\n"], &b["junk/super"]);
    printf(&a["WHAT%c%c%c  %c%c  %c !\n"], 
 1["this"],2["beauty"],0["tool"],0["is"],3["sensitive"],4["CCCCCC"]);
        
    return 0;  
}
参考答案:本例是合法的,输出如下:
    Hello! what is this? super 
    That  is  C !
本例主要展示了一种另类的用法。下面的两种用法是相同的:
    "hello"[2]    2["hello"]
如果你知道:a[i] 其实就是 *(a+i)也就是 *(i+a),所以如果写成 i[a] 应该也不难理解了。


5、要对绝对地址0x100000赋值,我们可以用*(unsigned int*)0x100000 = 1234;那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
答:
((void (*)())0x100000)();

首先要将0x100000强制转换成函数指针,即:
(void (*)())0x100000

然后再调用它:
((void (*)())0x100000)();

用typedef可以看得更直观些:
typedef void (*voidFuncPtr)();
((voidFuncPtr)0x100000)();


6.结构体:

结构体成员对齐规则:

1.每一个成员的起始地址必须是某个数的倍数。(这个数是cpu字长和成员自身大小之间的 最小值)

2.结构体整体大小必须是最大成员和cpu字长两者之间最小值的倍数。


struct' node{

int  a;

char b;

char c;

int   d;

int e;

}

struct node s={3,4,5,6};

struct node*p=&s;

printf("%d",(int*)p+3);  //0


7.数组指针

static void test2()
{
int a[] = { 1, 2, 3, 4, 5 };
int *p = (int*)(&a + 1); //&a的类型是int (*)[5], &a指向的类型是int [5]
printf("%d %d\n", *(a + 1), *(p - 1)); //2 5
}


8.strcpy

试题2:  //ps:(注意)
void test2()
{
  char string[10], str1[10];
  int i;
for(i=0; i<10; i++){
         str1[i] = 'a';
  }
  strcpy( string, str1 );
  printf("%s", string);
}
解答:
由于str1末尾没有'\0'结束标志,所以strcpy不知道拷贝到何时结束, 因此陷入死循环;
strcpy( char *s1,char *s2)的工作原理是,扫描s2指向的内存,逐个字符复制到s1所指向的内存,直到碰到'\0',因为str1结尾没有'\0',所以具有不确定性,不知道后面还会复制什么内容。 
printf函数,对于输出char* 类型,顺序打印字符串中的字符直到遇到空字符('\0')或已打印了由精度指定的字符数为止。
如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值