C/C++培训
达内IT学院
400-996-5531
一、变量与值得比较
1、布尔变量与零值的比较
不可将布尔变量直接与 TRUE、 FALSE或者 1、 0进行比较 。据布尔类型的语义,零值为“ 假”(记为 FALSE),任何非零值都是“ 真”(记为TRUE)。
TRUE的值究竟是什么并没有统一的标准。例如 Visual C++ 将 TRUE定义为 1, 而 Visual Basic则将 TRUE定义为-1 。假设布尔变量名字为 flag,它与零值比较的标准 if语句如下:
if (flag) // 表示flag为真
if (!flag) // 表示flag为假
其它的用法都属于不良风格,例如:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)
2、整形变量与零值的比较
应当将整型变量用“ ==” 或“ !=” 直接与 0比较 。假设整型变量的名字为 value,它与零值比较的标准 if语句如下:
if (value == 0)
if (value != 0)
不可模仿布尔变量的风格而写成:
if (value) // 会让人误解 value是布尔变量
if (!value)
3、浮点变量与零值的比较
不可将浮点变量用“ ==” 或“ !=” 与任何数字比较 。千万要留意, 无论是 float还是 double类型的变量, 都有精度限制。
所以一定要避免将浮点变量用“ ==” 或“ !=” 与数字比较,应该设法转化成“ >=” 或“ <=” 形式。假设浮点变量的名字为 x,应当 将:
if (x == 0.0) // 隐含错误的比
转化为:
if ((x>=-EPSINON) && (x<=EPSINON))
其中 EPSINON是允许的误差(即精度) 。
4、指针变量与零值的比较
应当将指针变量用“ ==” 或“ !=” 与 NULL比较 。指针变量的零值是“ 空”(记为 NULL)。尽管 NULL 的值与 0相同,但是两者意义不同。假设指针变量的名字为 p,它与零值比较的标准 if语句如下:
if (p == NULL) // p与 NULL显式比较,强调 p是指针变量
if (p != NULL)
不要写成:
if (p == 0) // 容易让人误解 p是整型变量
if (p != 0)
或者:
if (p) // 容易让人误解p是布尔变量
if (!p)
二、变量及基本运算
1、整型数
如果我们确定整数非负,就应该使用unsigned int而不是int。有些处理器处理无符号unsigned 整形数的效率远远高于有符号signed整形数(这是一种很好的做法,也有利于代码具体类型的自解释)。
因此,在一个紧密循环中,声明一个int整形变量的最好方法是:
registerunsignedint variable_name;
记住,整形in的运算速度高浮点型float,并且可以被处理器直接完成运算,而不需要借助于FPU(浮点运算单元)或者浮点型运算库。尽管这不保证编译器一定会使用到寄存器存储变量,也不能保证处理器处理能更高效处理unsigned整型,但这对于所有的编译器是通用的。
例如在一个计算包中,如果需要结果精确到小数点后两位,我们可以将其乘以100,然后尽可能晚的把它转换为浮点型数字。
2、除法和取余数
在标准处理器中,对于分子和分母,一个32位的除法需要使用20至140次循环操作。除法函数消耗的时间包括一个常量时间加上每一位除法消耗的时间。
Time (numerator / denominator) = C0 + C1* log2 (numerator / denominator)
= C0 + C1 * (log2 (numerator) - log2 (denominator)).
对于ARM处理器,这个版本需要20+4.3N次循环。这是一个消耗很大的操作,应该尽可能的避免执行。有时,可以通过乘法表达式来替代除法。例如,假如我们知道b是正数并且b*c是个整数,那么(a/b)>c可以改写为a>(c*b)。
如果确定操作数是无符号unsigned的,使用无符号unsigned除法更好一些,因为它比有符号signed除法效率高。
3、取模的一种替代方法
我们使用取余数操作符来提供算数取模。但有时可以结合使用if语句进行取模操作。考虑如下两个例子:
uint modulo_func1 (uint count)
{
return (++count % 60);
}
uint modulo_func2 (uint count)
{
if (++count >= 60)
count = 0;
return (count);
}
优先使用if语句,而不是取余数运算符,因为if语句的执行速度更快。这里注意新版本函数只有在我们知道输入的count结余0至59时在能正确的工作。
4、使用数组下标
如果你想给一个变量设置一个代表某种意思的字符值,你可能会这样做:
switch ( queue )
{
case0 : letter = 'W';
break;
case1 : letter = 'S';
break;
case2 : letter = 'U';
break;
}
或者这样做:
if ( queue == 0 )
letter = 'W';
elseif ( queue == 1 )
letter = 'S';
else
letter = 'U';
一种更简洁、更快的方法是使用数组下标获取字符数组的值。如下:
staticchar *classes="WSU";
letter = classes[queue];
5、使用别名
考虑如下的例子:
void func1( int *data )
{
int i;
for(i=0; i<10; i++)
{
anyfunc( *data, i);
}
}
尽管*data的值可能从未被改变,但编译器并不知道anyfunc函数不会修改它,所以程序必须在每次使用它的时候从内存中读取它。如果我们知道变量的值不会被改变,那么就应该使用如下的编码:
void func1( int *data )
{
int i;
int localdata;
localdata = *data;
for(i=0; i<10; i++)
{
anyfunc ( localdata, i);
}
}
这为编译器优化代码提供了条件。
6、局部变量的类型
我们应该尽可能的不使用char和short类型的局部变量。对于char和short类型,编译器需要在每次赋值的时候将局部变量减少到8或者16位。
这对于有符号变量称之为有符号扩展,对于无符号变量称之为零扩展。这些扩展可以通过寄存器左移24或者16位,然后根据有无符号标志右移相同的位数实现,这会消耗两次计算机指令操作(无符号char类型的零扩展仅需要消耗一次计算机指令)。
可以通过使用int和unsigned int类型的局部变量来避免这样的移位操作。这对于先加载数据到局部变量,然后处理局部变量数据值这样的操作非常重要。无论输入输出数据是8位或者16位,将它们考虑为32位是值得的。
考虑下面的三个函数:
int wordinc (int a)
{
return a + 1;
}
short shortinc (short a)
{
return a + 1;
}
char charinc (char a)
{
return a + 1;
}
尽管结果均相同,但是第一个程序片段运行速度高于后两者。
对于以上的C语言变量的使用技巧你还了解哪些?当你还在担心能否就业时,达内学员提前被企业录取;当你转辗于各大招聘会时,达内学员收到了高薪offer;当你在各大招聘网站投递简历时,达内学员中有人一毕业进入五百强名企。所以选择很重要。找C++培训班,选达内就对了。
填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!
Copyright © 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有
Tedu.cn All Rights Reserved