本系列博客基于董山海的<C和C++程序员面试秘笈>,旨在记录,欢迎交流,可联系 zywang@shu.edu.cn !
第二章:预处理、const、static 与 sizeof
文章目录
1、面试题1
预处理的使用
#include <stdio.h>
#include <stdlib.h>
//定义了名为DEBUG的预处理器常量
#define DEBUG
//
int main() {
int i = 0;
char c;
while (1) {
i++;
c = getchar();
if (c != '\n') {
getchar();
}
if (c == 'q' || c == 'Q') {
#ifdef DEBUG //这边判断DEBUG是否被订回来
printf("we got:%c,about to exit.\n", c);
#endif // DEBUG
break;
}
else {
printf("i=%d", i);
#ifdef DEBUG
printf(",we got:%c", c);
#endif // DEBUG
printf("\n");
}
}
return 0;
}
2、面试题2
用 #define 实现宏并求最大值和最小值
#define MAX(x,y) (((x)>(y))?(x):(y))
#define MIN(x,y) ((x)>(y))?(x):(y)
//在这里需要把参数小心的用括号括起来,因为宏只是简单的文本替换,括起来可以解决歧义的问题。
// 注意的是宏定义展开是在预处理时期,也就是编译之前,所有宏定义的参数能加括号就全加。
//
#include <stdio.h>
#include <iostream>
#define SQR(x) (x*x)
int main() {
int a, b = 3;
a = SQR(b + 2);
printf("a = %d\n", a);
system("pause");
return 0;
}
//此时a=11,而将上面#define SQR(x) (x*x)改为#define SQR(x) ((x)*(x)),a=25
3、面试题3
宏参数的连接
//宏参数的连接
#include <stdio.h>
#include <iostream>
#define STR(s) #s //使用#把宏参数变成一个字符串
#define CONS(a,b) (int)(a##e##b) //这边用##把两个宏参数贴在一起 也就是aeb
int main() {
printf(STR(vck));
printf("\n");
printf("%d\n", CONS(2, 3)); //也就是2e3=2000
system("pause");
return 0;
}
4、面试题4
用宏定义得到一个字的高位和低位字节,一个字由两个字节组成
//用宏定义得到一个字的高位和低位字节,一个字由两个字节组成
#define WORD_LO(xxx) ((byte) ((word)(xxx) & 255)) //低8位
#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8 )) //高8位
5、面试题5
用宏定义得到一个数组中所含的元素个数
//用宏定义得到一个数组中所含的元素个数
#define ARR_SIZE(a) ( sizeof((a)) / sizeof((a[0])) )
//解释:sizeof(array)为总大小,sizeof(a[0])表示一个int大小、为了保证宏定义不会发生"二义性",在a以及a[0]上都加了括号。
6、面试题6
const:
c
o
n
s
t
i
n
t
∗
const \ int*
const int∗:
c
o
n
s
t
const
const 在
i
n
t
∗
int*
int∗ 左侧,用来修饰指针所指向的变量,也就是指针指向常量;
i
n
t
∗
c
o
n
s
t
int* \ const
int∗ const:
c
o
n
s
t
const
const 在
i
n
t
∗
int*
int∗ 右侧,用来修饰指针本身,即指针本身为常量;
c
o
n
s
t
i
n
t
∗
c
o
n
s
t
const \ int* \ const
const int∗ const:表示指针本身不能修改,指针指向的内容也不能修改;
7、面试题7
c
o
n
s
t
const
const 以及 #define 的特点和区别
#define 用来做文本替换,生命止于编译期,存在于程序的代码段,实际上程序中只是一个常数,没有实际的存在;
const常量存在于程序的数据段,并在堆栈分配了空间。
#define没有数据常量,而const常量有数据类型。
8、面试题8
C + + C++ C++ 中 c o n s t const const 有什么作用?
- c o n s t const const 用于定义常量: c o n s t const const 定义的常量编译器可以对其进行数据静态类型安全检查;
- c o n s t const const 修饰函数 形式参数:当输入参数为用户自定义类型和抽象数据类型时,值传递变为const &传递,可以提高效率;
- const 修饰函数的返回值;
- const修饰类的成员函数(函数定义体);
9、面试题9
static有什么作用?
- 在函数体,一个被声明为静态的变量在这一函数被调用的过程中维持其值不变;
- 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所有函数访问到,但是不能被模块外其他函数所访问,它是一个本地的全局变量;
- 在模块内,一个被声明为静态的函数只可被这一模块内的其他函数调用。即这个函数被限制在声明它的模块的本地范围内使用。
10、面试题10
static全局变量和普通的全局变量之间的去吧:
非静态全局变量作用域为:整个源程序;
而静态全局变量的作用域:当前源文件中;
11、面试题11
C++类的静态成员
#include <iostream>
using namespace std;
class widget {
public:
//
widget() {
count++;
}
//
~widget() {
--count;
}
//类widget有一个静态方法num()
static int num() {
return count;
}
private:
static int count; //类widget有一个静态成员count
};
int widget::count = 0;
int main() {
widget x, y;
cout << "The Num.is" << widget::num() << endl;
if (widget::num() > 1) {
widget x, y, z;
cout << "The Num.is" << widget::num() << endl;
}
widget z;
cout << "The Num.is" << widget::num() << endl;
system("pause");
return 0;
}
12、面试题12
使用 s i z e o f sizeof sizeof 计算普通变量所占空间的大小
char str[] = "Hello";
char *p = str;
int n = 10;
sizeof(str)=6 //因为str的总大小为 strlen("Hello")+1,这个1表示的为字符串结束符
sizeof(p)=4 //这个p为指针,在32位 WinNT 平台下,指针为4个字节
sizeof(n)=4 //这个n为int型变量,在32位 WinNT 平台下,指针为4个字节
void Func(char str[100]) {
sizeof(str)=4 //指针
}
void *p = malloc(100);
sizeof(p)=4 //指针
13、面试题13
sizeof与strlen的区别
- s i z e o f sizeof sizeof 为操作符, s t r l e n strlen strlen 为函数;
- s i z e o f sizeof sizeof 操作符的结果类型为 size_t,它在头文件 t y p e d e f typedef typedef 为 u n s i g n e d i n t unsignedint unsignedint 类型,该类型保证能容纳实现所建立的最大对象的字节大小;
- sizeof 可以用类型做参数,strlen只能用 char 做参数,且必须以 “\0” 结尾*;
- 最主要的是:计算指针所占的内存空间大小,用sizeof;而计算字符串的长度,用strlen;
14、面试题14
#pragma pack的作用
#include <iostream>
using namespace std;
//
#pragma pack(1) //将对齐设为1,如果注释,编译器默认对齐为8
//
struct test {
char c;
short s1;
short s2;
int i;
};
int main() {
cout << sizeof(test) << endl;
system("pause");
return 0;
}
用 #pragma pack将对齐设为 1 1 1。由于结构体 t e s t test test 中的成员 s 1 , s 2 s1,s2 s1,s2和i的自身对齐分别为2、2和4,都大于1。因此都是用1作为对齐,那么sizeof(test)=1+2+2+4=9;
如果注释,那么编译器默认的为8,因为都小于8,那么都使用自身的对齐,那么 sizeof(test)=1+1+2+2+2+4=12;
15、面试题15
内联函数
- i n l i n e inline inline 函数可以完全取代表达式形式的宏定义;
- 可以用内联函数来作为接口函数来读取类成员的数据;
- 内联函数以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率;
- 函数体内的代码比较长,使用内联将导致内存消耗代价较高;
- 如果函数体内出现循环,那么执行函数体内代码的时间比函数调用的开销大;
- 内联函数是在编译时候展开,而宏在预编译时展开;
- 宏不是函数,inline函数是函数;
- #define 一般把参数括起来,防止出现二义性,而内联函数不会出现二义性;