《C和C++程序员面试秘笈》第5章 位运算与嵌入式编程

1. 位制转换

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
int main()
{
	int i = 5.01;
	float f = 5;

	printf("%f\n", 5);//内存访问越界,结果不可预料
	printf("%lf\n", 5.01);//5.010000//5.01是double类型
	printf("%f\n", f);//5.000000//f是float类型,都是浮点类型时相互转换是相对安全的

	printf("%d\n", 5.01);//5.01占8个字节,而%d读取4个字节,因此结果不可预料
	printf("%d\n", i);//5
	
	system("pause");
	return 0;
}

32位平台中,intfloat都占4个字节,double8个字节
printf()%f认为参数是个double类型(printf函数中,float会自动转换成double)所以,%f从栈中读取8个字节
	因此,第1printf()内存访问越界,结果不可预料
	第4printf()5.018字节,而%d只读取4字节,结果不可预料
	

2. 位运算

要清楚各种数据类型在内存中的大小、所占位数、所占字节、及各种进制所占的字节数
利用位移操作来做乘除法效率是最高的

3. 设置或者清除特定的位

题目:
	整数a
	1. 设置a的bit 3
	2. 清除a的bit 3
解析:
	用#define和bit masks操作,这是一个有极高可移植性的方法。
总结:
	|=&= 分别用来置1和置0

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#define BIT3 (0x1 << 3)
void set_bit3(int &a)
{
	a |= BIT3; // |=0不变,|=1置为1
}
void clear_bit3(int &a)
{
	a &= ~BIT3; //&=1不变,&=0置为0
}
int main()
{
	int a = 0;
	set_bit3(a);
	cout << a << endl; //8
	clear_bit3(a);
	cout << a << endl; //0

	system("pause");
	return 0;
}

4. 计算一个字节里有多少bit被置1

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
using namespace std;
#define BIT7 (0x1 << 7)//一个字节有8位,将一个字节的最高位置成1
//
int calculate(unsigned char c)
{
	int count = 0, i = 0;
	unsigned char compare = BIT7;
	int len = sizeof(c) * 8;
	for (i = 0; i < len; i++)
	{
		if ((c & compare) != 0)
		{
			count++;
		}
		compare = compare >> 1;
	}
	return count;
}
int main()
{
	int c = 0;
	cin >> c;
	cout << calculate(c) << endl;
	
	system("pause");
	return 0;
}

5. 位运算–指定位 置零

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdio.h>
using namespace std;
#define BIT_MASK(bit_pos) (0x01 << bit_pos)
//相应位置置为0
int Bit_Reset(unsigned int &val, unsigned char pos)
{
	if (pos >= (sizeof(unsigned int) * 8))
	{
		return 0;
	}
	val &= (~BIT_MASK(pos));
	return 1;
}
int main()
{
	unsigned int a = 0x02;
	cout << a << endl;

	Bit_Reset(a, 2 - 1); //把第 2位置为0,其余位不变
	cout << a << endl;

	system("pause");
	return 0;
}

6. 运用位运算 交换a、b两数

swap(int &a,int &b)
{
	a^=b;
	b^=a;
	a^=b;
}
注意:
	只能用于相同类型数的交换

7. C++的4种运算符转化以及它们的不同点

1const_cast操作符
	1、将限制为const成员函数的const定义解除
2dynamic_cast操作符
	1、可以将基类指针,指向不同的派生类,然后将被转型为基类的对象还原成原来的对象(子类对象)
	限于对象指针的类型转换,而不是对象变量
3reinterpret_cast操作符
	它潜在危险,除非有充分理由,否则不要使用它
	1、通常用于,某些非标准的指针数据类型转换
4static_cast操作符
	1、用在父类子类 对象和指针类型之间进行类型转换
	2、数字(原始数据类型)类型之间进行类型转换,通常用来将大类型转换为小类型

8. 用#define声明一个常量

#define YEAR_TIME (60*60*24*365)UL
注意:
	1、不能以分号结束
	2、括号的使用
	3、需要时要告诉编译器常数的类型
	比如:此处,UL表示无符号长整型,

9. 如何用C语言编写死循环

while(1){}

10. 访问特定位置的内存

题目:
	设置一绝对地址为0x67a9的整型变量的值为0xaa66,编译器是一个纯粹的ANSI编译器

int *ptr;
ptr=(int *)0x67a9;
*ptr=0xaa66;
  1. 对中断服务代码的评论

12. 整数的自动转换

void foo()
{
	unsigned int a=6;
	int b=-20;
	if(a+b>6)//若a固定等于6,那么使表达式<=6的b的范围为 ~[-6,0];
		puts(">6");//此处>6
	else
		puts("<6");
}

总结:
	//表达式中同时存在有符号数和无符号数,有符号数自动转换为无符号数
问题:
	具体怎么转换的??????
	参看Chapter01-6-P9

13. 关键字static的作用

静态全局变量:只能在本源文件使用
静态函数:只能在本源文件内调用
静态局部变量:只能在该函数内部使用,并且调用过程之中维持其值不变

14. 关键字volatile的含义

	一个被定义为volatile的变量,是说这个变量可能会被意想不到的改变,这样,编译器就不会去假设这个变量的值了。
	准确地说,就是优化器在用到这个变量时,必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份
	几个例子:
		1、并行设备的硬件寄存器(如:状态寄存器)
		2、一个中断服务子程序中会访问到的非自动变量
		3、多线程应用中被多个任务共享的变量

15. 判断处理器是大端还是小端

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
using namespace std;

//相应位置置为0
int checkCPU()
{
	union w // 注意:联合体union的存放顺序是 所有成员都从低地址开始存放
	{
		int a;
		char b;
	}c;
	c.a = 1;
	return (c.b == 1);//小端返回1,大端返回0
}
int main()
{
	cout << checkCPU() << endl;
		
	system("pause");
	return 0;
}

16. 处理器字长

unsigned int zero = 0;
unsigned int compzero = ~0;//不能写成0xFFFF, 因为 数据类型的大小 依赖处理器字长
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值