C代码常见问题

1.代码行重复
案例:
pTab->ItemNumber = 5;
pTab->Item[0].Type = DATA_TYPE_INT;
pTab->Item[0].Len = 4;
pTab->Item[1].Type = DATA_TYPE_STRING;
pTab->Item[1].Len = 5;
pTab->Item[2].Type = DATA_TYPE_STRING;
pTab->Item[2].Len = 5;
pTab->Item[3].Type = DATA_TYPE_STRING;
pTab->Item[3].Len = 10;
pTab->Item[4].Type = DATA_TYPE_STRING;
pTab->Item[4].Len = 10;
对Item赋值重复对Item赋值重复
重复代码在复制粘贴时容易忘记修改某些符号而导致难以发现的错误,如果没有单元测试的话将会是很糟糕的。
重复代码还给代码阅读、维护带来麻烦。
【建议】
消除重复,类似本案例可以采用提炼函数、for循环、定义时初始化等方式。
消除重复是重构的首要的、最主要的一项工作。在不断消除重复的重构过程中会自然地改善代码的可维护性。
如, 填写Items的代码可以重构为:
TABLE_ITEM items[] = {
{DATA_TYPE_STRING,0, VRF_NAME_LENGTH + 1},
{DATA_TYPE_STRING,0, LEN_IP_ADDRESS + 1},
{DATA_TYPE_STRING,0, LEN_IS_ZTENMS},
};
fillTableItems(pTable, &items[0],sizeof(items)/sizeof(items[0]));
其中,fillTableItems可定义为可供所有命令行显示部分调用:
static void fillTableItems(TABLE_DATA * pTable, const TABLE_ITEM * pItems, const UINT8 num)
{
memmove(pTable, pItems, sizeof(TABLE_ITEM)* num);
pTable->Item = num;
}

2.字节自然对齐
【案例】
typedef struct _LinkVlanTable_T
{
UINT32 ifId;
UINT16 vlanId;
UINT8 relateType;
UINT16 vlanflag;
VLANTRANSTABLE_T vlanTrans;
struct _LinkVlanTable_T *pLinkNext;
struct _LinkVlanTable_T *pLinkTail;
struct _LinkVlanTable_T *pVlanNext;
struct _LinkVlanTable_T *pVlanTail;
} MGPACK LINKVLANTABLE_T;
【说明】
非自然对齐的数据结构定义,如果再采用紧缩模式,那么其最主要缺点的是效率问题(如果不用紧缩模式只是结构的size不直观,容易造成浪费。当然不同产品对接时可能出现问题)。对于有些CPU还存在严重的稳定性问题(好像是IPMUX吧,如果访问不能被4整除的指针地址(非自然对齐),则产生异常任务会挂起,我们原先的平台为了防止发生这样的挂起故障,在底层进行了处理,将这样的指针地址访问进行了转换,这样严重影响了效率和系统的稳定性)
【类似问题】
板间交互数据的字段定义更应是自然对齐的,应像RFC报文的字段定义那样都是自然对齐的。
【建议】
1. 数据结构定义应该是自然对齐的。
2. 板间交互数据的字段定义应是自然对齐的
3. 非板间交互,则不必要采用紧缩模式 (如果自然对齐则无所谓紧缩模式了)
4. 可以考虑:禁止使用单字节紧缩模式(嗯,反逼着数据结构定义做到自然对齐)

3.头文件包含
【说明】
有些同学创建新文件时,首先找个参考源文件把其包含的头文件连同文件头注释一起拷贝过来。这样导致文件包含了不少不需要的头文件,增加预编译的耗时,也使得文件结构关系不够清晰。
【相似问题】
头文件也应仅包含其自身所需的头文件。
【建议】
无论源文件还是头文件,仅应包含该文件所自身所需的头文件。
如果只有一个源文件使用的定义,应放在此源文件中,而不要放在任何头文件中。
一个模块提供给外部的接口(及类型定义、宏定义)应集中放在该模块的对外公开头文件(_ex.h)中。不同级别的模块应有不同级别的接口公开头文件,一个接口只应在一个头文件中公开(如,当一个接口的公开范围由三级模块提升为二级模块时,应将该接口从三级模块公开头文件中移到二级公开头文件中)。
可以采用工具分析头文件包含关系,将头文件包含关系理顺。

4.多次调用
【案例】
if(!Comm_IsMateMpInService()||!Comm_GetSysLoadBalanceState() || Comm_GetLoadBalanceSlaveDisableState())
{
。。。。。。
}
else if(Comm_IsMateMpInService())
{
。。。。。。
}
【说明】
判断条件重复调用了 Comm_IsMateMpInService()。当Comm_IsMateMpInService()为TRUE时会连续执行2遍,降低了效率。
【建议】
修改使之只执行一遍。如:
static BOOL isMateMPInNormal(void)
{
return ( Comm_IsMateMpInService() &&
Comm_GetSysLoadBalanceState() &&
!Comm_GetLoadBalanceSlaveDisableState());
}

5.过多局部变量
【说明】
局部变量太多主要有以下几个问题:
1. 压栈出栈时间消耗
2. 消耗栈空间,应注意栈空间会否有溢出可能
3. 代码冗长复杂,可维护性差
局部变量太多常常是代码未做很好的抽象和分层,摊大饼式实现代码,如果做好抽象,那么常常会将这些局部变量拆分到不同的分支路径的子函数中,甚至部分不需要了。也即做好抽象其实会减少代码执行流程中的栈消耗,减少压栈和出栈,一般仅此节省的压栈出栈就比多调用几层子函数(即增加几级调用深度)的效率高(且编译器会自动进行一些优化,适时进行内嵌减少一些跳转)。
局部变量太多最大的问题是因未进行很好的抽象而使代码冗长复杂,可维护性差。局部变量太多的函数一般代码行数大、分支多、嵌套深、重复多、可读性差,缺陷难以定位、修改代码风险高、可维护性差。

6.复杂的if判断多用函数
【案例】
if( BGP_CAP_PRO_TCP == *(pData+BGP_CAP_PRO_TCP_OFFSET+tagOffset) &&
(BGP_CAP_PORT == *(pData+BGP_CAP_PORT_OFFSET_SRC+tagOffset) ||
BGP_CAP_PORT == *(pData+BGP_CAP_PORT_OFFSET_DES+tagOffset) ) )
{
if(s_BgpCap.semRx == TRUE)
return; 丢弃?
s_BgpCap.semRx = TRUE;
BgpCap_PktRcv(pData, dataLen);
s_BgpCap.semRx = FALSE;
}
【建议】
这部分应写得更清晰些,如增加嵌套、提炼函数
???? if (isXXXPkt())
if (is…Pkt() && is…Pkt()…)

7.栈空间
【案例】
void BgpCap_FillPcap(void)
{
BGPCAPNODE arraySortedA[MAX_BGP_CAP_NODE_SUM],arraySortedB[MAX_BGP_CAP_NODE_SUM]; 栈空间 ???
。。。。。。
}
【建议】
动态分配

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值