Chinaunix首页 | 论坛 | 博客
  • 博客访问: 319165
  • 博文数量: 64
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 1972
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-31 21:53
个人简介

文明之精神,野蛮之体魄。

文章分类
文章存档

2015年(4)

2013年(60)

我的朋友

分类: C/C++

2013-09-06 15:47:34

一、逻辑运算符使用分析
1.短路规则:
---||从左向右开始计算,当遇到条件为真的条件时停止计算,整个表达式为真,所有条件为假时表达式才假。
---&&从左向右开始计算,当遇到条件为假时停止计算,整个表达式为假,所有条件为真时表达式才为真。
Example:
int g = 0;
int f()
{
    return g++;
}
int main()
{
    int i = 0; 
    int j = 0;
    if(++i > 0 || ++j > 0){
        printf("%d\n",i);
        printf("%d\n",j);
    }
    if( f() && f() ){
        printf("%d\n",g);
    }
    printf("%d\n",g);
    return 0;
}
2.C语言中逻辑符“ !”只认得0,只知道见了0就返回1.因此当其作用的值不是0时,其结果为0.

二、位运算符分析
1.左移和右移注意点
---左移运算符<<将运算符数的二进制位左移。规则:高位丢弃,低位补0
---右移运算符>>将运算符数的二进制位右移。规则:高位补符号位,低位丢弃
---左移n位相当于乘以2的n次方,但效率比数学运算符高
---右移n为相当于除以2的n次方,但效率比数学运算符高
Example:
  1 #include
  2
  3 #define SWAP(a,b)\
  4 {               \
  5     int temp = a;\
  6     a = b;      \
  7     b = temp;   \
  8 }
  9 #define SWAP1(a,b)\
 10 {                 \
 11     a = a + b;\
 12     b = a - b;\
 13     a = a - b; \
 14 }
 15 #define SWAP2(a,b)\
 16 {               \
 17     a = a ^ b;  \
 18     b = a ^ b;  \
 19     a = a ^ b;  \
 20 }
 21
 22 int main()
 23 {
 24     int a = 1;
 25     int b = 2;
 26 //    SWAP1(a,b);
 27     SWAP2(a,b);
 28     printf("a = %d,b = %d\n",a,b);
 29     return 0;
 30 }
Example:有一个数列,其中的自然数都是以偶数的形式出现,只有一个自然数出现的次数为奇数次。编程找出这个自然数。
  1 #include
  2
  3 #define DIM(a) (sizeof(a)/sizeof(*a))
  4
  5 int main()
  6 {
  7     int a[] = {2,3,5,7,2,2,2,5,3,7,1,1,1};
  8     int find = 0;
  9     int i = 0;
 10     for(i = 0; i < DIM(a); i++){
 11         find = find ^ a[i];
 12     }
 13     printf("find = %d\n",find);
 14     return 0;
 15 }
三、类型转换分析
1.C语言隐式类型转换
---算术运算式中,低类型转换为高类型
---赋值表达式中,表达式的值转换为左边变量的类型
---函数调用时,实参转换为形参的类型
---函数返回时,return表达式转换为返回值类型

char }   int ->  unsigned int -> long -> unsigned long ->double <- float
short}
Example:
  1 #include
  2
  3 int main()
  4 {
  5     int i = -2;
  6     unsigned int j = 1;
  7
  8     if((i + j) >= 0){
  9         printf("i + j >= 0\n");
 10     }else{
 11         printf("i + j < 0\n");
 12     }
 13
 14     printf("i + j = %d\n", i + j);
 15     printf("i + j = %0X\n",i + j);
 16     return 0;
 17 }
Result:
mq@ubuntu:~/program/cpro$ ./a.out
i + j >= 0
i + j = -1

四、编译过程
1.预编译
处理所有的注释,以空格代替
将所有的#define删除,并且展开所有的宏定义
处理条件编译指令#if, #ifdef, #elif, #else, #endif
处理#include,展开被包含的文件
保留编译器需要使用的#pragma指令
预处理指令:gcc -E file.c -o file.i

2.编译
对预处理文件进行一系列词法分析,语法分析和语义分析
词法分析主要分析关键字,标示符,立即数等是否合法
语法分析主要分析表达式是否遵循语法规则
语义分析在语法分析的基础上进一步分析表达式是否合法
分析结束后进行代码优化生成相应的汇编代码文件
编译指令: gcc -S file.c -o file.s

3.汇编
汇编器将汇编代码转变为机器可以执行的指令
每个汇编语句几乎都对应一条机器指令
汇编指令:gcc -c file.s -o file.o

五.宏定义与使用分析
 #define定义宏常量可以出现在代码的任何地方
 #define从本行开始,之后的代码都可以使用这个宏常量
 #define表达式给有函数调用的假象,却不是函数
 #define表达式可以比函数更强大
 #define表达式比函数更容易出错
2.宏表达式与函数的对比
宏表达式在预编译期被处理,编译器不知道宏表达式的存在
宏表达式用“实参”完全替代形参,不进行任何运算
宏表达式没有任何的“调用”开销
宏表达式中不能出现递归定义
3.强大的内置宏
__FILE__ 被编译的文件名
__LINE__ 当前行号
__DATE__ 编译时的日期
__TIME__ 编译时的时间
__STDC__ 编译器是否遵循标准C规范

Example:定义日志宏
  1 #include
  2 #include
  3
  4 #define LOG(s){                                        \
  5     time_t t;                                             \
  6     struct tm* ti;                                        \
  7     time(&t);                                              \
  8     ti = localtime(&t);                                  \
  9     printf("%s[%s:%d]%s\n",asctime(ti),__FILE__,__LINE__,s);  \
 10 }
 11
 12 void f()
 13 {
 14     LOG("Enter f()...");
 15     LOG("Exit f()...");
 16 }
 17
 18 int main()
 19 {
 20     LOG("Enter main...");
 21     f();
 22     LOG("Exit main...");
 23
 24     return 0;
 25 }



阅读(1138) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~