项目中写代码的注意事项总结
在C++环境中如何利用预先声明好的C函数进行操作?这些问题都可以通过直接调用这些函数来解决。而对于那些希望在C语言环境中调用C++功能的情况来说,在编写代码时需要注意的是,在包含必要的头文件后应该明确地声明外部库函数的可见性,并确保它们能够正确地与现有代码集成工作。
#ifdef __cplusplus
extern "C"
{
#endif
函数的结尾加上
#ifdef __cplusplus
}
#endif
参考文献:C语言文件如何使用C++函数_陌上花开缓缓归以的博客
2,函数返回值一般用于返回错误码,不要用于直接返回函数的执行结果。
#define MAX_PORT 20
int test_fun(int port,int* buf)
{
if(port < 0 || port > MAX_PORT)
{
return -1;
}
if( buf == NULL)
{
return -1;
}
//buf用于保存数据
return 0;
}
参考文章:c语言论函数返回值的重要性_陌上花开缓缓归以的博客-博客_c语言的函数返回值的作用
3,有符号和无符号数据类型的混合运算,应注意类型转换;
#include<stdio.h>
//typedef unsigned int size_t;
//size_t sizeof( )
int main()
{
char *s = "tangtest";
if(sizeof(s) <= -1)
{
printf("sizeof(s) get length failure\n");//代码打印的这个
}
else
{
printf("sizeof(s)= %ld\n",sizeof(s));
}
return 0;
}
将if(sizeof(s) <= -1)改为 if((signed int)sizeof(s) <= -1)
立即数作为无符号类型使用时,后面应加上U标识.
#include<stdio.h>
int main()
{
signed int a = -1;
if(a < 1U)
{
printf("a < 1\n");
}
else
{
printf("a > 1\n");
}
if(a < 1)
{
printf("a < 1\n");
}
else
{
printf("a > 1\n");
}
return 0;
}
4,不要把子程序的参数用作工作变量,如果需要,另设一个临时变量来处理;
void process(int a,int b,int c);
int func(int arg1, int arg2, int arg3)
{
process(arg1, arg2, arg3);
return 0
}
建议尽量避免直接操作单个变量;推荐采用临时变量来存储后再进行相关运算。
void process(int a,int b,int c);
int func(int arg1, int arg2, int arg3)
{
int temp1 = arg1;
int temp2 = arg2;
int temp3 = arg3;
process(temp1, temp2, temp3);
return 0;
}
5,在项目中避免直接使用全局变量,并通常建议使用set和get函数来完成对全局变量的读写操作;
在项目管理中进行全局变量的配置与管理时,请详细阐述如何实现对全局变量的读取与存储操作的具体步骤与方法
6,在避免进行字符串复制操作时遇到存储空间不足的问题;必须确保每个字符串末尾都有一个NULL标识符;并且,在获取拷贝字符串的过程中也应该意识到宁可截断数据也不愿越界。
char g_dst[20] = {0};
int mycopy(char* src)
{
if(src == NULL)
{
return -1;
}
else if(strlen(src) >= 20)
{
memcpy(g_dst,src,19);
g_dst[20] ='\0';
}
else
{
memcpy(g_dst,src,strlen(src));
}
return 0;
}
- 函数返回值不应仅直接返回成功状态码0或错误状态码-1, 而应采用反映出具体错误信息的详细代码, 并遵循统一的编码规范.
typedef enum return_value
{
return_ok = 0,
read_failre = -1,
write_failure = -2,
para_error = -3,
not_ready = -4,
status_failure = -5
}RETURN_VALUE;
在函数实现过程中除了编写实现函数功能的代码之外还需要规范化地添加日志打印内容便于进行函数调试和维护工作
参考文献:C语言实现的日志记录系统(打印功能的具体实现)_陌上花开缓缓归以的文章-博客
- 建议尽可能避免使用除法运算法则, 尤其是在涉及浮点数的计算中, 因为进行一次浮点数除法操作通常会消耗较多的CPU资源. 这种情况下, 编译器能够减少不必要的循环迭代次数.
#define PI 3.1415926
float except_result(float num)
{
return num / PI;
}
#define PIP 1/3.1415926
float mult_result(float num)
{
return num * PIP;
}
10,注意运算表达式是否会导致缓冲区的上溢、下溢
11,在处理较为冗长的代码段时尤其是涉及多重嵌套的情况我们通常会在程序块结束后在其右侧添加注释说明以便明确标识该程序块的结束位置从而提升代码的整体可读性。
int function()
{
if(condition)
{
test_fun();
}/*******test fun******/
return 0;
}
12,在嵌套调用过程中应当特别注意操作顺序,在采用嵌套调用信号量进行保护操作时,请确保后被占用的信号量应优先进行释放操作而未及时释放已被占用的信号量而导致系统出现死锁问题。
int mutext_a;
int mutext_b;
int mutext_test()
{
pthread_mutext_lock(&mutext_a);
pthread_mutext_lock(&mutext_b);
test_fun();
pthread_mutex_unlock(&mutext_b);
pthread_mutex_unloc(&mutext_a);
return 0;
}
13,数组的下标尽量避免使用表达式,且下标表达式要做合法性检查;
对于字符串操作而言,在C语言中越界访问会导致不可预测的结果
14,非定长内存拷贝时应进行长度检查,确保拷贝不会越界;
参考文章:
15,进行非定长内存拷贝之前需检查拷贝字符串长度,确保拷贝不会越界。
该博客详细探讨了C语言内存管理中的常见问题及其解决方案。
文章重点分析了内存泄漏与句柄泄露的现象,
并提出了相应的防范措施。
在内存泄漏方面,
文章建议开发者应定期审查内存分配日志,
以确保程序运行过程中不会出现未释放的动态内存块。
此外,
对于句柄泄露的问题,
文章强调了对窗口句柄的安全性进行严格检查的重要性,
并建议采用适当的防护机制来防止此类漏洞的出现。
总结而言,
该博客为开发者提供了实用的技术见解与操作指导。
16,循环控制不能用char型变量,由于char型值范围是-128--127,可能出现死循环;
本文着重探讨了C语言中负数二进制翻转操作的实现方法。从计算机内部存储的角度来看,在现代计算机系统中,默认情况下所有整数值都可以采用补码编码方式来表示,并且这种编码方式具有良好的运算特性及溢出特性。对于正数值而言,在进行运算时其符号位始终为零;相反地,在进行运算时其符号位始终为一。例如,在十进制系统中类似的特性也适用于其他基数系统(如八进制或十六进制)。在本问题中我们关注的是针对有符号整数值的二进制反转操作这一特定情况,并提出了一种新的解决方法。具体转换步骤如下:首先将待转换的有符号整数值转换为其对应的机器码形式;其次对机器码进行逐位取反操作并加一得到最终结果;最后将结果还原为十进制形式即可完成转换过程。
17,多维数组的非零初始化应用括号指明维度; a[2][3] = {{0}};
第18步
注
enum color
{
red = 3,
blue,
green,
yellow = 5
};/*不推荐*/
enum color
{
red = 3,
blue = 4,
green = 5,
yellow = 5
};/*推荐*/
19,在进行位运算时,针对无符号char或unsigned short类型的变量所得的结果必须被强制转换回原数据类型。
Uint16_t result_16 = ((uint16_t)(~(uint16_t)port)) >> 4;
在编程过程中应尽量采用枚举类型来代替布尔类型(Bool),因为这种数据类型的值更具明确性并有助于提高代码可读性;建议完全避免采用布尔类型(Bool),因为其常量名称容易产生歧义且难以理解其真实含义;另外需要注意的是布尔类型的值在逻辑运算中不够稳定且不具备良好的扩展性特征
21,在项目中尽量避免过多使用可变长数组(VLA),尽管相比堆上动态申请的方式,在性能上具有一定的优势。然而因为我们的部分产品仍依赖于较早版本的编译器,在C99标准的支持程度上可能存在不足之处。这可能导致生成的可变长数组(VLA)代码存在缺陷,并进而导致难以排查的异常问题出现。
- 在处理for或while循环中的情况时,在每次执行以下操作前应在进入该操作前确保数组不会越界。
//计算数组中2-n个数据的总和
int sum(int* a,int n)
{
int sum = 0;
if( a == NULL)
{
return -1;
}
if(n < 2)
{
return 0;
}
for(int i = 0; i < n; i++)
{
if((i + 2) >= n)
{
break;
}
sum = sum + a[i+2];
printf("a[i+2] = %d,sunm =%d\n",a[i+2],sum);
}
return sum;
}
int a[3]={1,2,3}
int offset=0;
for(i=0;i<3;i++)
{
if((offset+2)>=3)
{
break;
}
offset +=2;
a[offset]=1;
}
23,同类宏定义采用枚举变量替代;
参考文章:C语言枚举数据类型的使用方法解析
24,调用有返回值的函数时要即时做异常处理,且风格要统一;
该文深入探讨了在C语言编程中函数返回值所发挥的关键作用及其重要性。文章指出,在程序设计中合理运用函数返回值不仅可以提高代码的可读性和可维护性,在特定情况下还能够显著提升程序的整体性能效率。此外,通过对函数返回值的深入分析与合理配置,还可以有效避免潜在的逻辑错误与运行异常问题,在软件开发过程中具有重要的实践指导意义。
25,函数栈变量长度不要超过1K,超过1k建议用malloc或者new分配堆内存。
26,尽量少使用变参函数,比如printf这种函数;
27,单个功能函数不要超过500行,嵌套不要超过?
28,结构体里面的元素字数不宜过多;
