C和C++程序员面试秘笈②

本系列博客基于董山海的<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 有什么作用?

  1. c o n s t const const 用于定义常量: c o n s t const const 定义的常量编译器可以对其进行数据静态类型安全检查;
  2. c o n s t const const 修饰函数 形式参数:当输入参数为用户自定义类型和抽象数据类型时,值传递变为const &传递,可以提高效率;
  3. const 修饰函数的返回值;
  4. const修饰类的成员函数(函数定义体);

9、面试题9

static有什么作用

  1. 在函数体,一个被声明为静态的变量在这一函数被调用的过程中维持其值不变;
  2. 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所有函数访问到,但是不能被模块外其他函数所访问,它是一个本地的全局变量;
  3. 在模块内,一个被声明为静态的函数只可被这一模块内的其他函数调用。即这个函数被限制在声明它的模块的本地范围内使用。

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的区别

  1. s i z e o f sizeof sizeof 为操作符, s t r l e n strlen strlen 为函数
  2. 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 类型,该类型保证能容纳实现所建立的最大对象的字节大小
  3. sizeof 可以用类型做参数,strlen只能用 char 做参数,且必须以 “\0” 结尾*;
  4. 最主要的是:计算指针所占的内存空间大小,用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 s1s2和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

内联函数

  1. i n l i n e inline inline 函数可以完全取代表达式形式的宏定义
  2. 可以用内联函数来作为接口函数来读取类成员的数据
  3. 内联函数以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率
  4. 函数体内的代码比较长,使用内联将导致内存消耗代价较高
  5. 如果函数体内出现循环,那么执行函数体内代码的时间比函数调用的开销大
  6. 内联函数是在编译时候展开,而宏在预编译时展开
  7. 宏不是函数,inline函数是函数
  8. #define 一般把参数括起来,防止出现二义性,而内联函数不会出现二义性
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值