面试题集锦

2.引用与指针有什么区别? 

  • 引用必须被初始化,指针不必。 
  • 引用初始化以后不能被改变,指针可以改变所指的对象。
  • 不存在指向空值的引用,但是存在指向空值的指针。

6.堆栈溢出一般是由什么原因导致的?      

  没有回收垃圾资源。

7.什么函数不能声明为虚函数? 
      构造函数不能声明为虚函数。

9.写出float x 与“零值”比较的if语句。      

  if(x>0.000001&&x<-0.000001)

12.IP地址的编码分为哪俩部分? 
     IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。

11.对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?    

  c用宏定义,c++用inline 

17

unsigned char *p1; 

unsigned long *p2; 
p1=(unsigned char *)0x801000;  

p2=(unsigned long *)0x810000; 

请问p1+5=   p2+5=   
答案:0x801005(相当于加上5位) 0x810020(相当于加上20位);

int *p1=(int*)0x00801000;
int *p2=(int*)0x00801004;

unsigned char *p3=(unsigned char *)0x00801000;
unsigned char *p4=(unsigned char *)0x00801004;

printf("%d ",p2-p1);//1
printf("%d ",p4-p3);//4

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

1. 用宏定义写出swap(x,y)

答#define swap(x, y) x = x + y; y = x - y; x = x - y;

2. 一语句实现x是否为2的若干次幂的判断 答:方法1)int i = 512; 
cout << boolalpha << ((i & (i - 1)) ? false : true) << endl; //位与为0,则表示是2的若干次幂

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. 以下代码中的两个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; 
答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。

  函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。    

注意:数组名作为函数参数时,退化为指针. 
        数组名作为sizeof()参数时,数组名不退化,因为sizeof不是函数. 

5. 指出下面代码的输出,并解释为什么。(不错,对地址掌握的深入挖潜) 

main() 


  int a[5]={1,2,3,4,5}; 

  int *ptr=(int *)(&a+1); 

  printf("%d,%d",*(a+1),*(ptr-1)); 


输出:2,5 
*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5 
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int) 
int *ptr=(int *)(&a+1);  
则ptr实际是&(a[5]),也就是a+5 原因如下:

&a是数组指针,其类型为 int (*)[5]; 
而指针加1要根据指针类型加上一定的值, 不同类型的指针+1之后增加的大小不同 
a是长度为5的int数组指针,所以要加 5*sizeof(int) 所以ptr实际是a[5] 
但是prt与(&a+1)类型是不一样的(这点很重要) 所以prt-1只会减去sizeof(int*) 
a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]. 

6.关键字volatile有什么含意?并举出三个不同的例子.

它是被设计用来修饰被不同线程访问和修改的变量

作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
 
7.int (*p)[n];------p为指向一维数组的指针,这个一维数组有n个整型数据。
 

3. 数组越界问题 (这个题目还是有点小险的) 下面这个程序执行后会有什么错误或者效果: 

#define MAX 255 

int main() 


  unsigned char A[MAX],i; 

  for (i=0;i<=MAX;i++) 

    A[i]=i; 


解答:MAX=255,数组A的下标范围为:0..MAX-1,这是其一,

其二 当i循环到255时,循环内执行: A[255]=255;这句本身没有问题,但是返回for (i=0;i<=MAX;i++)语句时,由于unsigned char的取值范围在(0..255),i++以后i又为0了..无限循环下去. 
注:char类型为一个字节,取值范围是[-128,127],unsigned char [0 ,255]

4.restrict是c99标准引入的,它只可以用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式.即它告诉编译器,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,而不能通过其它途径(其它变量或指针)来修改;这样做的好处是,能帮助编译器进行更好的优化代码,生成更有效率的汇编代码.如 int *restrict ptr, ptr 指向的内存单元只能被 ptr 访问到,任何同样指向这个内存单元的其他指针都是未定义的,直白点就是无效指针。

5.析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载。只是在类对象生命期结束的时候,由系统自动调用释放在构造函数中分配的资源。

 

//为了实现链式操作,将目的地址返回,加3分!

char * strcpy( char *strDest, const char *strSrc ) 

  assert( (strDest != NULL) && (strSrc != NULL) ); 

  char *address = strDest; 

  while( (*strDest++ = * strSrc++) != '’ ); 

  return address; 

}

(2)数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改; 
char str[10];  
str++; //编译出错,提示str不是左值

(3)数组名作为函数形参时,沦为普通指针。

试题3:写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。另外,当你写下面的代码时会发生什么事? 
least = MIN(*p++, b);  
 解答: 
#define MIN(A,B) ((A) <= (B) ? (A) : (B))

MIN(*p++, b)会产生宏的副作用

宏定义#define MIN(A,B) ((A) <= (B) ? (A) : (B))对MIN(*p++, b)的作用结果是: ((*p++) <= (b) ? (*p++) : (b)) 

++被执行两次

试题4:为什么标准头文件都有类似以下的结构?  
#ifndef __INCvxWorksh 

#define __INCvxWorksh  

#ifdef __cplusplus  
extern "C" 

#endif  

/*...*/  
#ifdef __cplusplus 

}  
#endif  
#endif /* __INCvxWorksh */ 

该函数被C编译器编译后在symbol库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息,C++就是考这种机制来实现函数重载的。   为了实现C和C++的混合编程,C++提供了C连接交换指定符号extern "C"来解决名字匹配问题,函数声明前加上extern "C"后,则编译器就会按照C语言的方式将该函数编译为_foo,这样C++中就可以调用C语言的函数了。

试题5:编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh” 

void func(char sz[],int step)
{
  int n=strlen(sz);
  char *temp = new char[n+1];
  for(int i=0;i<n;i++)
  {
    temp[(i+step)%n]=sz[i];
  }
  temp[n]='';
  strcpy(sz,temp);
}

试题7:编写类String的构造函数、析构函数和赋值函数,已知类String的原型为: 
class String {  
public:  
  String(const char *str = NULL); // 普通构造函数    

  String(const String &other); // 拷贝构造函数    

  ~ String(void); // 析构函数  
  String & operate =(const String &other); // 赋值函数   

private:  
  char *m_data; // 用于保存字符串  

};  
解答: 
//普通构造函数

String::String(const char *str)  { 
  if(str==NULL)   { 
    m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志''的空   

    //加分点:对m_data加NULL 判断   

    *m_data = '';   

  }  

  else  { 

    int length = strlen(str);  
    m_data = new char[length+1]; // 若能加 NULL 判断则更好    

    strcpy(m_data, str);   

  } 

}  
// String的析构函数  
String::~String(void)  


   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::operate =(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;         //得分点:返回本对象的引用 

试题1:请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1   

解答: 
int checkCPU() 

{  

  union w   {  
    int a;    

    char b[sizeof(int)];   

  } c;   

  c.a = 1; 

  return (c.b[0] == 1);  

}  

试题:逐层打印二叉树节点值

分析 采用宽度优先搜索

void LinePrint(Tree *T)
{
  deque<Node*>Que;
  Que.push_back(T->root);
  while(!Que.empty())
  {
    Node *p = Que.front();
    Que.pop_front();
    printf("%d ",p->key);
    if(p->left != NIL)
    {
      Que.push_back(p->left);
    }
    if(p->right != NIL)
    {
      Que.push_back(p->right);
    }

  }
}

原文地址:https://www.cnblogs.com/johnsblog/p/3890692.html