博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

预处理、const与sizeof(面试宝典读书笔记二)

Posted on 2011-04-01 17:54  ¥忘%风  阅读(2394)  评论(7编辑  收藏  举报

程序员面试宝典读书笔记(二)

一:宏定义 

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

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 <stdio.h>
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 = %d\n", 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
1:What is the output of the following code ?
#include <stdio.h>
struct Node1 {
    char a3;
    int a1;
    short a2;
};

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

int main() {
    printf("%d\n", sizeof(Node1));
    printf("%d\n", sizeof(Node2));
    return 0;
}

Answer: 
结构体对齐:以结构体里最长的数据单元为对齐单元。
    所以结构体的长度是最长的数据元素的整数倍。
sizeof(Node1);
|char|---|---|---|
|-------int------|
|--short-|-------|

sizeof(Node2);
|-------int------|
|char|---|-short-|
12 8
相关知识,点击链接:sizeof(结构体)和内存对齐
 

2:sizeof() 和 strlen() 的区别?
相关知识,点击链接:sizeof和 strlen 的区别


3:下面程序输出什么? 
#include <stdio.h>
int main() {
    int a = 4;
    printf("%d\n", sizeof(a = 6));
    printf("%d\n", 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 <stdio.h>
char var[10];
int test(char var[]) {
    return sizeof(var);
}
int main() {
    printf("%d\n", test("hello world"));
    return 0;
}
Answer: 
C/C++传递数组永远是传递数组的首地址,是一个指针。
即int test(char var[]);等价于int test(char var *);等价于int test(char var[8]);
只要是指针类型,sizeof的大小就是4。
4


5:一个空类的空间占多少? 多重继承的空类呢?
Answer:一个空类所占的空间为1,多重继承的空类所占的空间仍然为1。
Sample:
#include <iostream>
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;
}


6:内联函数与宏定义的差别是什么?
相关知识,点击链接:内联函数与宏


原创文章如转载请注明:转自¥忘%风 {http://www.cnblogs.com/slave_wc}

本文地址: 预处理、const与sizeof(面试宝典读书笔记二)