一套面试题总结代码

作者:袖梨 2022-06-25

一套面试题总结代码

面试例题1:
如何用一个宏定义find求一个结构体ctype里某个变量cnum相对了ctype的编移量 ?
如:


view sourceprint?stuct student 

    int a; 

    char b[20]; 

    double ccc; 

}

则:
find(student,a);     //等于0
find(student,b);    //等于4

 

answer: 

#define find(struc, e) (size_t)&(((struc*)0)->e)
(struc*)0           //表示将常量0强制转化为struc *型指针所指向的地址
&(((struc*)0)->e)       /*表示取结构体指针(struc*)0的成员e的地址,因为该结构体的首地址为0,
                          所以其实就是得到了成员e距离结构体首地址的偏移量.*/
(size_t)                     //是一种数据类型,为了便于不同系统之间移植而定义的一种无符号型数据,
                                     一般为unsigned int*/
(struc*)0                   // 表示假设在0地址处有一个结构体struc
((struc*)0)->e               // 表示在0地址处的结构体struc的成员e
&(((struc*)0)->e)           // 表示在0地址处的结构体struc的成员e 的地址
(size_t)&(((struc*)0)->e)    //将0地址处的结构体struc的成员e 的地址转换成整数类型

 

二:const
1: what does the keyword "const" means in c program ? please at least make
    two examples about the usage of const.

 

parse:在c程序中,const的用法主要有定义常量、修饰函数参数、修饰函数返回值等3个用处。
    在c++程序中,它还可以修饰函数的定义体,定义类中某个成员函数为恒态函数,即不改
    变类中的数据成员。

answer:
(1)可以定义const常量。
(2)const可以修饰函数的参数和返回值,甚至函数的定义体。被const修饰的东西都受到强
    制保护,可以预防意外的变动,能提高程序的健壮性。

2:const 与 #define相比有什么不同 ?
c++语言可以用const定义常量,也可以用#define定义常量,但是前者比后者有更多的优点.

 

answer:
(1)const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行安全检查,而对后者
    只进行字符替换,没有类型安全检查,并且在字符替换中可能会产生意料不到的错误(边际效应).

(2)有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试.在c++程序
    中只使用const常量而不使用宏常量,即const常量完全取代宏常量.
相关知识,点击链接: c++中的常量

3:在下述情况下,如果要修改类的成员变量,应该怎么办
class a_class
{
    void f() const
    {
  
    }
}
answer:
在const成员函数中,用mutable修饰成员变量名后,就可以修改类的成员变量了。
sample
#include
class c {
private:
    mutable int m_count;
    
public:
    c(int i):m_count(i) {}
    int add() const {
        return ++m_count;
    }  
  
    int minus() const {
        return --m_count;
    }
  
    int print() {
        printf("m_count = %dn", m_count);
    }
};

int main() {
    c tmp(5);
    printf("before add: ");
    tmp.print();
    tmp.add();
    printf("after add : ");
    tmp.print();
    puts("");
    printf("before minus: ");
    tmp.print();
    tmp.minus();
    printf("after minus : ");
    tmp.print();
    return 0;
}
sizeof
#include
struct node1 {
    char a3;
    int a1;
    short a2;
};

struct node2 {
    int a1;
    char a3;
    short a2;
};

int main() {
    printf("%dn", sizeof(node1));
    printf("%dn", sizeof(node2));
    return 0;
}
answer:
结构体对齐:以结构体里最长的数据单元为对齐单元。
    所以结构体的长度是最长的数据元素的整数倍
sizeof(node1);
|char|---|---|---|
|-------int------|
|--short-|-------|

sizeof(node2);
|-------int------|
|char|---|-short-|
下面程序输出什么?

#include
int main() {
    int a = 4;
    printf("%dn", sizeof(a = 6));
    printf("%dn", a);
    return 0;
}
answer:
sizeof不是函数,也不是一元运算符,它是类似宏定义的特殊关键字,sizeof()括号内
的内容在编译过程中是不被编译的,而是被替代类型,如int = 8; sizeof(a)。在编译
过程中不管a是什么值,只是被替代成类型sizeof(int),结过为4。如果是sizeof(a = 6)
呢?也一样是转换成sizeof(int),但需要注意的是:a = 6是不被编译的,所以执行完后,
a的值不变。
4 4
4:下面代码的输出结果是什么?
#include
char var[10];
int test(char var[]) {
    return sizeof(var);
}
int main() {
    printf("%dn", test("hello world"));
    return 0;
}
answer:
c/c++传递数组永远是传递数组的首地址,是一个指针。
即int test(char va[]);等价于int test(char var *);等价于int test(char var[8]);
只要是指针类型,sizeof的大小就是4。
4


5:一个空类的空间占多少? 多重继承的空类呢?
answer:一个空类所占的空间为1,多重继承的空类所占的空间仍然为1。
sample:
#include
using namespace std;
class a {};
class a1 {};
class b : public a {};
class c : public virtual b {};
class d : public a, public a1 {};

int main() {
    cout << sizeof(a) << endl;
    cout << sizeof(b) << endl;
    cout << sizeof(c) << endl;//虚继承设计到虚表(虚指针),所以sizeof(c)的大小为4
    cout << sizeof(d) << endl;
    return 0;
}
内联函数与宏定义的差别

 


内联函数和普通函数相比可以加快程序运行的速度,因为不需要中断调用,在编译的时候内联函数可以直接呗镶嵌到目标代码中。

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

inline是指嵌入代码,就是在调用函数的地方不是跳转,而是把代码直接写到那里去。对于短小的代码来说,inline可以带来一定的效率提升,

而且和c时代的宏函数相比,inline更安全可靠。可是这个是以增加空间消耗为代价的。至于是否需要inline函数就需要根据你的实际情况取舍了。

  inline一般只用于如下情况:

  (1)一个函数不断被重复调用。

  (2)函数只有简单的几行,且函数不包含for、while、switch语句。

  ●一般来说,我们写小程序没有必要定义成inline,但是如果要完成一个工程项目,当一个简单函数被调用多次时,则应该考虑用inline。

  ● 宏在c语言里极其重要,而在c++里用得就少多了。关于宏的第一规则是:绝不应该去使用它,除非你不得不这样做。几乎每个宏

   都表明了程序设计语言里或者程序里或者程序员的一个缺陷,因为它将在编译器看到程序的正文之前重新摆布这些正文。宏也许

   是许多程序设计工具的麻烦。所以,如果你使用了宏,你就应该准备着只能从各种工具(如排错系统、交叉引用系统、轮廓程序等)

     中得到较少的服务。(--pass:宏还是很方便的,使用时要小心,并不是说宏一无是处,存在自然有其合理性)

 


  宏是在代码处不加任何验证的简单替代,而内联函数是将代码直接插入调用处,而减少了普通函数调用时的资源消耗。

  宏不是函数,只是在编译前(编译预处理阶段)将程序中有关字符串替换成宏体。

  inline函数是函数,但在编译中不单独产生代码,而是将有关代码嵌入到调用处。


inline fact(float i) { return i * i; } // 没有写返回值的printf("bb= %d", fact(8)); // 调用时就是执行printf("bb= %d", 8*8);

相关文章

精彩推荐