首页 > 代码库 > 2017年1月15日 11:20:59杂项
2017年1月15日 11:20:59杂项
位操作
位操作的必要性:通过串口或并口与其他器件相连
&按位与
|按位或
^按位异或:两位相异时为1,相同时为0.
上述三个操作满足结合律和交换率。
左移运算符:<<将要运算的二进制位左移
规则:高位丢弃,低位补0.
使用格式:
int a = 1<<1;
a = 2;
右移运算符:>>讲要运算的二进制右移
规则:高位补符号位,地位丢弃。
符号位:若为正数则符号位是0,负数符号位为1。
小技巧:
左移n位相当于乘以2的n次方,但效率比数学运算高。
右移n位相当于除以2的n次方,但效率比数学运算高。
防错准则:
避免位操作运算符,逻辑运算符和数学运算符同出现在一个表达式中
当位运算符,逻辑运算符和数学运算符需要同时参与运算时,尽量使用括号()来表达计算次序。
嵌入式比较讲究效率!
加减法的优先级高于左移和右移。
交换两个变量:利用#define和\代码块替换
#define SWAP1(a,b) \
{ \
int temp = a; \
a = b; \
b = temp; \
} \
#define SWAP2(a,b) \
{ \
a = a + b; \
b = a - b ; \
a = a - b ; \
} \
问题:如果a很大,b很大,a+b的值可能会使a溢出。
#define SWAP3(a,b) \
{ \
a = a ^ b; \
b = a ^ b ; \
a = a ^ b ; \
} \
位运算符的效率比加减高得多,整数交换建议用第三种方法。
某个面试题:
有一个数列,其中的自然数都是以偶数的形式存在,只有一个自然数出现的次数为奇数次,找出这个数。
贪心法——++,--表达式阅读技巧
1.编译器处理的每个符号应该尽可能多的包含字符
2.编译器从左像右一个一个尽可能多的读入字符
3.当即将读入的字符不可能和已读入的字符组成合法符号为止。
程序编译的四个步骤:
由.c和.h文件经过预处理cpp产生.i文件,再经过编译器gcc,产生.s文件,经过汇编器as产生.o文件,.o和.a文件经过链接器产生.out文件。
预编译阶段:
处理掉所有注释,用空格代替。
将#define删除,展开所有的宏
处理条件编译指令#if,#ifdef,#elif,#else,#endif.
处理#include,展开被包含的文件
保留编译器需要使用的#pragma指令
预处理指令:gcc-E file.c-o hello.i
编译阶段:
对预处理文件进行一系列的词法分析,语法分析和语义分析
词法分析:关键字,标示符,立即数等
语法分析:表达式是否遵循语法会泽
语义分析:在语法分析的基础上进一步分析
生成.i文件
分析结束后,进行代码优化生成相应的汇编代码文件
编译指令: gcc-S file.c -o hello.s
生成.s文件。
链接器:将.o文件和库文件装载在一起,生成最终可执行文件。
与源代码密切相关的,预处理,编译,汇编。
链接器
作用:把各个模块之间相互引用的部分处理好,使个个模块正确衔接。
#define定义宏常量可以出现在代码的任何地方
#define从本行开始,之后的代码都可以使用这个宏常量。
#define 别名 原内容
#define 路径用法:
#define PATH_1 D:\XYZ\test.c
#define表达式有函数调用的假象,却不是
#define表达式可以比函数更强大
#define表达式比函数更容易出错
printf(“%d\n”,((i++<j) ? (i++) : (j)));
宏表达式在预编译期被处理,编译器不知道宏表达式的存在
宏表达式用“实参”完全替代形参,不进行任何计算。
宏表达式没有任何“调用”开销
宏表达式不能出现递归定义
宏定义的范围
#define X 256
//以下可使用,直到#undef X
#undef X
强大的内置宏
宏 含义 示例
_FILE_ 被编译的文件名 file1.c
_LINE_ 当前行数 25
_DATE_ 编译时日期 Jan312012
_TIME_ 编译时时间 17:01:01
_STDC_ 是否遵循标准C规范 1
定义日志宏
如果用函数来写日志:
void log(char* s)
{
printf(“%s %d %s\n”,_FILE_,_LINE_,s); //行
}
如果在文件中不停调用这个函数,会发现显示的第二个数据一直为函数定义时的行数。
因为要调用这个函数时,需要跳回函数执行,这样只会输出定义函数时的行数。
这时需要用到宏定义
#define LOG(s) \printf(“%s %d %s\n”,_FILE_,_LINE_,s);
这几个信息不够,还需要加上时间
先包含时间头文件,#include “time.h”
void f()
{
time_t t;
struct tm* ti;
time(&t);
ti = localtiome(&t);
printf(“%s %d %s”,asctime(ti),_LINE_,_FILE_,s);
}
如何将这个函数加到宏定义
#define LOG(s) do{ \
time_t t; \
struct tm* ti; \
time(&t); \
ti = localtime(&t); \
printf(“%s [%s %d],%s”,asctime(ti),_FILE_,_LINE_,s); \
}while(0);
牛叉的续行符!
课后思考:
#define f (x) ((x)-1)
宏代表什么意思?对空格敏感么?宏“调用”对空格敏感么
2017年1月15日 11:20:59杂项