解析:
通过这道题面试官想考以下几个知识点:
答案:#define SECOND_EVERY_YEAR (606024*365)UL
解析:
这个测试是为下面的目的而设的
注意点
:一定要带好括号,不要嫌麻烦,因为宏操作是直接替换,如果不带括号会出现一些问题,请看下面的例子#define SQUARE(x) x * x
int a = 4;
int b = SQUARE(a + 1);
在预处理阶段,SQUARE(a + 1) 会被替换成 a + 1 * a + 1,由于乘法的优先级高于加法,所以实际上会计算成 a + (1 * a) + 1,结果为 9 而不是 25。
答案:#define MIN(x, y) ((x) <= (y) ? (x) : (y))
解析:
关于const修饰指针的情况,一般分为如下4种情况:
int main()
{
int b = 500;
const int* a = &b; // 情况1
int const* a = &b; // 情况2
int* const a = &b; // 情况3
const int* const a = &b; // 情况4
return 0;
}
int b = 500;
const int* a = &b;
*a = 600; // 错误
但是也有别的办法去改变*a的值,一个是通过改变b的值:
int b = 500;
const int* a = &b;
b = 600;
cout << *a << endl; // 得到600
还有一种改变*a办法就是a指向别处(管理员换个仓库):
int b = 500, c = 600;
const int* a = &b;
a = &c;
cout << *a << endl; // 得到600
int b = 500, c = 600;
// int *const a; // 错误 没有初始化
int *const a = &b; // 正确,必须初始化
*a = 600; // 正确,允许改值
a = &c; // 错误,指针是常量
cout << a++ << endl; // 错误
int b = 500, c = 600;
const int* const a = &b;
a = &c; // 错误
*a = 600; // 错误
答案:
#include
#include
#include
using namespace std;
struct {
short a1;
short a2;
short a3;
}A;
struct {
long a1;
short a2;
}B;
int main()
{
char *ss1 = "0123456789";
char ss2[] = "0123456789";
char ss3[100] = "0123456789";
int ss4[100];
char q1[] = "abc";
char q2[] = "a\n";
char *q3 = "a\n";
char *str1 = (char *)malloc(100);
void *str2 = (void *)malloc(100);
cout << sizeof(ss1) << " ";
cout << sizeof(ss2) << " ";
cout << sizeof(ss3) << " ";
cout << sizeof(ss4) << " ";
cout << sizeof(q1) << " ";
cout << sizeof(q2) << " ";
cout << sizeof(q3) << " ";
cout << sizeof(A) << " ";
cout << sizeof(B) << " ";
cout << sizeof(str1) << " ";
cout << sizeof(str2) << " ";
return 0;
}
解析:
答案: 4 11 100 400 4 3 4 6 8 4 4
#include
using namespace std;
class A {
private:
bool m_bTemp;
int m_nTemp;
bool m_bTemp2;
};
class B {
private:
int m_nTemp;
bool m_bTemp;
bool m_bTemp2;
};
int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
return 0;
}
解析:
在访问内存时,如果地址按4字节对齐,则访问效率会高很多。这种现象的原因在于访问内存的硬件电路。一般情况下,地址总线总是按照对齐后的地址来访问的。例如你想得到0x00000001开始的4字节内容,系统首先需要以0x00000000读4字节,从中取得3字节,然后再用0x00000004作为开始地址,获得下一个4字节,再从中得到第一个字节,两次组合出你想得到的内容。但是如果地址一开始就是对齐到0x00000000,则系统只要一次读写即可。
答案:12 8
解析:
由以下几个例子我们说明sizeof和strlen之间的区别。
第1个例子:
char * ss = "0123456789";
sizeof(ss)结果为4,ss是指向字符串常量的字符指针。
sizeof(*ss)结果为1,*ss是第一个字符。
第2个例子:
char ss[] = "0123456789";
sizeof(ss)结果为11,ss是数组,计算到“\0”位置,因此是(10+1)。
sizeof(*ss)结果为1,*ss是第一个字符。
第3个例子:
char ss[100] = "0123456789";
sizeof(ss)结果为100,ss表示在内存中预分配的大小,100×1。
strlen(ss)结果为10,它的内部实现是用一个循环计算字符串的长度,直到“\0”为止。
第4个例子:
int ss[100] = "0123456789";
sizeof(ss)结果为400,ss表示在内存中的大小,100×4。
strlen(ss)错误,strlen的参数只能是char*,且必须是以“\0”结尾的。
第5个例子:
class X
{
int i;
int j;
char k;
};
X x;
cout< 答案: 通过对sizeof与strlen的深入理解,得出两者区别如下: 答案: 解析:sizeof问题,3×4×4=48。 答案:C 解析:我们用程序来实现一个空类和一个多重继承的空类。看看它们的大小是多少。代 空类所占空间为1,单一继承的空类空间也为1,多重继承的空类空间还是1。 答案:1 1 4 1 答案: 一般来说,我们写小程序没有必要定义成inline,但是如果要完成一个工程项目,当一个简单函数被调用多次时,则应该考虑用inline。 而如下风格的函数Foo则成为内联函数: 所以说,inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。内联能提高函数的执行效率,至于为什么不把所有的函数都定义成内联函数?如果所有的函数都是内联函数,还用得着“内联”这个关键字吗?内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。 以下情况不宜使用内联:
占内存的大小。
个操作符而不是个函数。
组时,sizeof返回全部数组的尺寸。sizeof操作符不能返回被动态分配的数组或外部的数组的
尺寸。
fun(char [8])、fun(char [])都等价于fun(char *)。在C++里传递数组永远都是传递指向数组首
元素的指针,编译器不知道数组的大小。如果想在函数内知道数组的大小,需要这样做:进
入函数后用memcpy将数组复制出来,长度由另一个形参传进去。代码如下:void fun (unsigned char *p1, int len)
{
unsigned char* buf = new unsigned char[len+1];
memcpy(buf, p1, len);
}
存储大小数据的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void
类型等。8.说明sizeof的使用场合
void *malloc(size_t size);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
9. 这个数组占据多大空间?
int **a[3][4] = ?
A. 64
B. 12
C. 48
D. 128
10.一个空类占多少空间?多重继承的空类呢?
码如下:#include
但是虚继承涉及虚表(虚指针),所以sizeof©的大小为4。11.内联函数和宏的差别是什么?
一个函数不断被重复调用。
函数只有简单的几行,且函数内不包含for、while、switch语句。inline void Foo(int x, int y); // inline仅与函数声明放在一起
void Foo(int x, int y) {}
void Foo(int x, int y);
inline void Foo(int x, int y) {} // inline与函数定义放在一起
1 如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。
2 如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。类的构造函数和析构函数容易让人误解成使用内联更有效。要当心构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。一个好的编译器将会根据函数的定义体,自动地取消不值得的内联(这进一步说明了inline不应该出现在函数的声明中)。