预处理、const与sizeof
程序员面试宝典读书笔记(二)
一:宏定义
面试例题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-|
相关知识,点击链接: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; }
C/C++传递数组永远是传递数组的首地址,是一个指针。
即int test(char va[]);等价于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(面试宝典读书笔记二)