C/C++语言程序设计缺陷(1)---符号误用

C/C++语言程序设计缺陷(1)

符号误用问题

符号是程序的一个基本组成单元,其作用相当于句子中的单词,每个符号都有其特定的含义。在程序语句中,符号的误用常常引起语句错误,导致程序异常。

1.布尔型变量被赋值

例1:

void f(bool flag)
{
    int a;
    bool ok;
    ok=true;
    if(flag=ok) // flag是一个bool型变量
    a++;
}

例1中,第6行条件判断语句,存在布尔型变量flag被赋值的错误。

2.“==”运算符与“=”赋值符混用

由于“= =”运算符和“=”赋值符形似,二者经常混用。例2和例3中的if语句应使用运算符“==”,但误用了赋值符“=”。
例2:

void foo(int i, int j)
{
    int t;
    if(i=j)
    t++;
}

例2中,第4行语句本意是比较i和j的值是否相等,而“if(i=j)”执行的操作是把j值赋给i,再判断i的值是否为0。
例3:

class A
{
    int t;
    int q();
};
main()
{
    int num;
    A a;
    if (i=a.q())
    {
      num++;
    }
}

例3中,第10行条件判断语句中,“==”判断符误用为“=”赋值符,函数调用语句出现在if条件判断语句“=”赋值符的右边。
例4:

f()
{return 1;}
main()
{
    int a;
    int array[3]={1,12,13};
    if ((a==array[2])< 0)
    f();
    else return -1;
}

例4中,第7行语句本意是将array[2]赋值给a后,再将a的值和0作比较,如果条件为真则执行函数f();当使用“==”后,“(a= =array[2])”的值只能是0或1,不会小于0,函数f()永远不会执行。

3.按位运算符“&”、“|”和逻辑运算符“&&”、“||”混用

例5:

f()
{return 1;}
main()
{
    int a=8;
    int b=1;
    if(a&b) f();
}

例5中,第7行条件判断语句“if(a&b)”本意是逻辑与运算“&&”,被误用为按位与运算符“&”后,“8&1”结果为0,函数f()将不会执行。

4.单引号‘ ’和双引号“ ” 字符混用

程序中单引号的字符,比如’a’代表一个字符,字符在编译器中有其对应字符集中的序列值,也可以说单引号字符代表一个整数;而双引号代表一个字符串,字符串在编译器中代表一个指向无名数组起始字符的指针。
例6:

main ()
{
  char * p;
  p='a';
}

例6中,指针P是字符型的指针,‘a’代表一个整数,赋值号两边的数据类型不匹配。

5.赋值表达式错用其他操作符

例7:

int main(int k)
{
    int j=1;
    k=0;
    if(j)
    {
        j>k;
        return j;
    }
    else
    {
        k++;
        return k;
    }
}

例7中,第7行语句错用操作符“>”代替赋值表达式操作符“=”,使得该语句没有任何意义。

6.分号使用不当

程序中不小心多了或少了一个分号,这个分号也许会作为不会产生任何实际效果的空语句,但在某些情况下,却可能造成不良后果。
例8:

#include <stdlib.h>
main()
{
    int a, c ;
    int array[3]={10, 06, 12};
    scanf("%d",&a);
    if(a < 0);
        c=a;
}

例8中,第7行语句多了一个分号,那么紧跟在if语句之后的语句“c=a;”就是一条单独的语句,和条件判断部分完全没有任何关系了。
例9:

#include <stdlib.h>
void f()
{
  int a;
  float array[3];
  scanf("%d",&a);if (a < 0)
  return
  array[2]=a;
}

例9中,第9条语句少了一个分号,程序会把“array[2]=a;”语句中分号之前的内容作为return的返回内容,而该程序中函数f()不应返回任何内容。
有时程序中会误用中文分号作为程序中所使用的英文分号,在这种情况下,编译器会对这个错误的分号产生一条告警信息。

7.自增/自减(++/–)运算符和变量间有空格

程序中无论是自增或自减运算符,运算符和变量之间不能有空格。
例10:

main()
{
    int i=6;
    int j=7;
    -- i;
    j ++;
}

例10中,自减或自增符号和变量i、j之间都有空格,为了增加程序的可读性,应该去除自减或自增符号和变量i、j间的空格。

8.错误使用自增/自减(++/–)运算符

自增/自减运算符(++/–)表达简练,因此在C/C++编程中会经常用到,但就是这个几乎在每个程序中都会用到的运算符,如果不注意细节,就会产生错误。
例11中的程序遍历数组arr[10]的每个元素,如果元素的值不等于2,则执行自增/自减操作,并打印自增/自减后的值。
例11:

#include<stdio.h>
int main()
{
    int arr[10] = {2,3,1,2,3,3,1,2,2,3};
    int tmp = 0;
    for(int i = 0; i<10; i++)
    {
        if(arr[i] < 2)
    	{
        tmp = arr[i]++;
        printf("arr[%d] = %d\n", i, tmp);
    	}
    	else if(arr[i] > 2)
      	{
       		tmp = arr[i]--;
        	printf("arr[%d] = %d\n", i, tmp);
      	}
    }
 return 0;
}

按照程序设计意图,每次打印语句中的元素值应该都是2,但是查看结果发现,打印出来的值没有变,这是因为错误使用了自增/自减运算符。
单独使用a++和++a时,其结果是一样的,都相当于a=a+1,但tmp= a++和tmp= ++a得到的结果是不一样的:
tmp= a++,相当于tmp = a;a=a+1。
tmp= ++a,相当于a=a+1;tmp = a。
前者先赋值再自增,后者先自增再赋值,即包含的赋值操作的顺序不一样,结果也就不一样了,同时两者的效率也不一样,对于a++,需要用一个临时变量来保存a的值,然后执行自增操作;而对于++a来说,整个表达式的值就是a的值,无需进行中间值的复制操作,因此其效率要高一些。
在例11中,第11行语句和第17行语句赋给tmp的值并非是数组元素自增/自减后的值,而是数组元素本来的值。
在需要使用自增/自减运算符时,如无特殊情况,建议使用++a(–a)格式的语句。

9.字符串结束符被误用

C语言中没有专门的字符类型,通常用字符数组来存放字符串,以’\0’作为字符串的结束符。如果结束符’\0’被误用为"\0"时,可能导致程序崩溃。
例12:

Main()
{
    char  a[10];
    for(i=0;i<9;i++)
    a[i]=i;
    a[9]= '\0';f(a);
}

例12中,第6行语句欲把‘\0’作为结束符赋值给字符型数组a的最后一个元素,在这种情况下,C++编译器不会把字符‘\0’赋值给一个数组元素,但C编译器会这样做。这种错误在编程时不易察觉,需要注意。

10.对浮点型变量进行相等比较

浮点数在内存中的存储机制和整数不同,有舍入误差,在计算机中用以表示某个近似实数,但无法精确。具体来说,这个实数由一个整数或定点数乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基数为10的科学记数法。因为浮点数是非精确存储,所以比较浮点数是否相等时时,不能用关系运算符中的“= =”、“!=”、“>=”和“<=”进行比较运算。
例13:

int  main()
{
    float  a;
    float  b;if(a==b)
    return 1;}

例13的第6行语句中,直接使用关系运算符“==”比较两个浮点数是否相等。当需要判断两个浮点数是否相等时,应该先设定一个精度,比较两个浮点数差的绝对值是否在这个精度范围内。
修改方法:将第6行语句改为“if(fabs(a-b) < 1.0E-10)”。

11.程序中运算符的优先级使用错误

编程时如果不知道运算符的优先级,可能导致程序中运算表达式错误,进而引起程序异常。
对于运算符之间的优先级,记住关键两点:
① 所有逻辑运算符的优先级都低于任何一个关系运算符;
② 移位运算符的优先级比算术运算符低,但比关系运算符高。
例14:

#include <stdlib.h>
main()
{
    int  a, b, c;
    scanf("%d",&a);
    scanf("%d",&b);
    c = ( a & b!=0 )
}

例14中,第7行语句本意是“c = ( (a & b)!=0 )”,即a和b先做按位与运算,运算后的值再和0作比较,但由于运算符“!=”的优先级大于“&”,所以条件表达式变为“c=(a&(b!=0))”,即b和0比较的结果,再和a值按位与运算,导致错误的结果。

12.使用逗号导致程序发生错误

例15:

void FpParser(USHORT *pUnit,USHORT carrierNumber,USHORT frameLen)
{if(snmp_var.syntax==SNMP_SYNTAX_OCTETS)
    {
	memcpy(cMsg,snmp_var.value.string.ptr,snmp_var.value.string.len),
    FpParser((USHORT*)cMsg,g_config.m_CarrNum, g_config m_FramLen); 
    }}

例15中第6行语句,函数之间用逗号分隔,在这种情况下,只返回最右边函数的值。
修改方法:分开写,都用分号。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值