《转自http://blog.chinaunix.net/space.php?uid=22534388&do=blog&id=184259》
C语言编程需注意的方面 (2011-03-22 21:06)
C语言编程需注意的方面 (2011-03-22 21:06)
一、书写风格
良好的编程风格是提高程序可靠性非常重要的手段,也是大型项目多人合作开发的技术基础。具体的变成格式每家公司都有规范,但作为一个初学者养成良好的编程风格还是有必要的。
1、空行的使用
空行起着分隔程序段落的作用。空行得体(不过多也不过少)将使程序的布局更加清晰。空行不会浪费内存,所以不要舍不得用空行。但空行也不宜太多,一般情况是这样的:
a、预处理语句后要加空行;
b、变量声明或函数声明之后加空行;
c、变量的声明与定义之间尽量加空行;
d、一个功能段结束之后加空行,如:if、while等语句完毕以后加空行;
e、程序返回return前加空行。
良好的编程风格是提高程序可靠性非常重要的手段,也是大型项目多人合作开发的技术基础。具体的变成格式每家公司都有规范,但作为一个初学者养成良好的编程风格还是有必要的。
1、空行的使用
空行起着分隔程序段落的作用。空行得体(不过多也不过少)将使程序的布局更加清晰。空行不会浪费内存,所以不要舍不得用空行。但空行也不宜太多,一般情况是这样的:
a、预处理语句后要加空行;
b、变量声明或函数声明之后加空行;
c、变量的声明与定义之间尽量加空行;
d、一个功能段结束之后加空行,如:if、while等语句完毕以后加空行;
e、程序返回return前加空行。
2、修饰符的使用
修饰符 * 和 & 应该靠近数据类型还是该靠近变量名,要靠个人的习惯,本人是将修饰符* 靠近变量定义的,因为靠近数据类型,例如:int* x; 从语义上讲此写法比较直观,即x是int 类型的指针。但这很容易引起误解,例如:int* x, y; 此处y容易被误解为指针变量。不益于程序的阅读。
修饰符 * 和 & 应该靠近数据类型还是该靠近变量名,要靠个人的习惯,本人是将修饰符* 靠近变量定义的,因为靠近数据类型,例如:int* x; 从语义上讲此写法比较直观,即x是int 类型的指针。但这很容易引起误解,例如:int* x, y; 此处y容易被误解为指针变量。不益于程序的阅读。
3、空格和括号的使用也要注意,尽量让程序清晰易读。
4、程序的注释是不可少的。
4、程序的注释是不可少的。
二、变量
1、变量定义的次序
最好把同类型的定义在一起,最好把长度小的定义在前面,这样可以优化存储器布局,有可能节约空间,特别是在嵌入式系统存储器比较紧张的情况下更是如此。
1、变量定义的次序
最好把同类型的定义在一起,最好把长度小的定义在前面,这样可以优化存储器布局,有可能节约空间,特别是在嵌入式系统存储器比较紧张的情况下更是如此。
2、变量的声明、定义和初始化
变量声明时赋值可以使程序简洁,很多情况下推荐使用,但有时会给程序带来麻烦,特别是在多文件模块的程序中,所以全局变量尽量先声明后赋值(全局变量只能赋初值一次)。
3、变量类型转换
整型与字符型的转换。
#include
变量声明时赋值可以使程序简洁,很多情况下推荐使用,但有时会给程序带来麻烦,特别是在多文件模块的程序中,所以全局变量尽量先声明后赋值(全局变量只能赋初值一次)。
3、变量类型转换
整型与字符型的转换。
#include
int main()
{
char a='2';
printf("%c\n", a);
printf("%d\n", a);
printf("%d\n", (int)a);
}
大家可以试试输出什么,所以不要想当然。
另外浮点型和整型的转换也要注意
{
char a='2';
printf("%c\n", a);
printf("%d\n", a);
printf("%d\n", (int)a);
}
大家可以试试输出什么,所以不要想当然。
另外浮点型和整型的转换也要注意
4、const修饰变量情况:
const char *p; //指向常量的指针,内容不可变,但指针可以变。
char * const p; //指针为常量,不可变,但内容可以变。
const char *p; //指向常量的指针,内容不可变,但指针可以变。
char * const p; //指针为常量,不可变,但内容可以变。
三、运算符及表达式
变量的值和表达式的值
i++和++i的区别:
i++是运算之后再加1;
++i是加1后再运算;
例(注意区别):
int main()
{
int i = 1;
变量的值和表达式的值
i++和++i的区别:
i++是运算之后再加1;
++i是加1后再运算;
例(注意区别):
int main()
{
int i = 1;
printf("%d\n", i++); //打印出来的为表达式(i++)的值 1;
}
}
int main()
{
int i = 1;
{
int i = 1;
printf("%d\n",++i); //打印出来的为表达式(++i)的值 2;
}
}
int main()
{
int i = 1;
{
int i = 1;
i++;
printf("%d\n",i); //打印出来的为变量i的值 2;
}
printf("%d\n",i); //打印出来的为变量i的值 2;
}
int main()
{
int i = 1;
{
int i = 1;
++i;
printf("%d\n",i); //打印出来的为变量i的值 2;
}
printf("%d\n",i); //打印出来的为变量i的值 2;
}
四、循环
1、循环的退出
循环的正常退出有四种方式:break、continue、exit、return,注意他们的区别:
break:完全退出循环;
continue:退出本次循环,继续下次循环;
exit:退出整个程序;
return:在子函数中,退出函数体,在main函数中退出整个程序。
1、循环的退出
循环的正常退出有四种方式:break、continue、exit、return,注意他们的区别:
break:完全退出循环;
continue:退出本次循环,继续下次循环;
exit:退出整个程序;
return:在子函数中,退出函数体,在main函数中退出整个程序。
2、循环的使用
a、嵌套循环中尽量将循环次数少的循环作为外循环,这样可以减少CPU跨切循环层的次数。
b、我们通常写循环都是这样的for(i=0; i
a、嵌套循环中尽量将循环次数少的循环作为外循环,这样可以减少CPU跨切循环层的次数。
b、我们通常写循环都是这样的for(i=0; i
3、无限循环
while(1)
{
}
要比
for(;;)
{
}
好一些。通常用while循环。
while(1)
{
}
要比
for(;;)
{
}
好一些。通常用while循环。
五、比较语句
比较语句中,千万要留意无论是float还是double类型的变量都有精度限制所以一定要避免将浮点变量用==或!=与数字比较应该设法转化成>=或<=形式。
动手试着写出与零比较的if语句。
比较语句中,千万要留意无论是float还是double类型的变量都有精度限制所以一定要避免将浮点变量用==或!=与数字比较应该设法转化成>=或<=形式。
动手试着写出与零比较的if语句。
六、函数
函数接口的两个要素是参数和返回值,编程过程中经常出现函数功能实现没问题,但就是不能得到正确的值。
1、函数的声明
void SetValue(int width, int height); //我们经常使用的格式
void SetValue(int, int); //不良的风格,但经常看到
float GetValue(void); //良好的风格
float GetValue(); //不良的风格,我们经常使用
函数接口的两个要素是参数和返回值,编程过程中经常出现函数功能实现没问题,但就是不能得到正确的值。
1、函数的声明
void SetValue(int width, int height); //我们经常使用的格式
void SetValue(int, int); //不良的风格,但经常看到
float GetValue(void); //良好的风格
float GetValue(); //不良的风格,我们经常使用
2、函数的返回值
C语言中,凡不加类型说明的函数,一律自动按整型处理。经常会被误解为void类型。
有的函数不需要返回值,但为了增加灵活性如支持链式表达,可以附加返回值。
函数调用结果的返回可以通过三种方式实现:全局变量,return,指针参数。
C语言中,凡不加类型说明的函数,一律自动按整型处理。经常会被误解为void类型。
有的函数不需要返回值,但为了增加灵活性如支持链式表达,可以附加返回值。
函数调用结果的返回可以通过三种方式实现:全局变量,return,指针参数。
3、函数的功能要单一,不要设计多用途的函数。
4、注意函数的形参和实参有各自的存储单元。
七、指针和数组
C程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以为两者是等价的。数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。 数组名对应着(而不是指向)一块内存,其地址与容量在程序运行的过程中保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是 “可变”,所以我们常用指针来操作动态内存。
易出错的地方:
C程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以为两者是等价的。数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。 数组名对应着(而不是指向)一块内存,其地址与容量在程序运行的过程中保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是 “可变”,所以我们常用指针来操作动态内存。
易出错的地方:
1、
int * p;
int q[10]; //声明指针和数组
++p; //正确
++q; //错误
数组名只对应一块内存,不可改变,内容可变;
指针指向一块内存,可改变。
int * p;
int q[10]; //声明指针和数组
++p; //正确
++q; //错误
数组名只对应一块内存,不可改变,内容可变;
指针指向一块内存,可改变。
2、
free(p); //释放后p并不等与NULL,只是将其指向的内容free掉了,如果在进行操作会带来不可预料的错误,常用的办法是在此句后面将p=NULL。
free(p); //释放后p并不等与NULL,只是将其指向的内容free掉了,如果在进行操作会带来不可预料的错误,常用的办法是在此句后面将p=NULL。
3、
像void fun(char str[10]){};这样以数组作为参数时一定要注意:
数组的长度是传不过来的这样 void fun(char str[10], int 10){};用一个整型数单独传数组的长度。
在函数中使用sizeof(str) //=4,因为在参数传递时传的是数组的地址(指针),不在是数组名了。
像void fun(char str[10]){};这样以数组作为参数时一定要注意:
数组的长度是传不过来的这样 void fun(char str[10], int 10){};用一个整型数单独传数组的长度。
在函数中使用sizeof(str) //=4,因为在参数传递时传的是数组的地址(指针),不在是数组名了。
4、
int i, *j;
scanf("%d", &i); //正确
scanf("%d", j); //错误,因为指针j为空指针,没有申请空间。
int i, *j;
scanf("%d", &i); //正确
scanf("%d", j); //错误,因为指针j为空指针,没有申请空间。
5、
char str[6] = "hello";
strlen(str) //=5,不包括'\0'。
sizeof(str) //=6,注意区分。
char str[6] = "hello";
strlen(str) //=5,不包括'\0'。
sizeof(str) //=6,注意区分。
6、
char p[] = "hello"; //存在栈空间,函数结束就释放了。
char *p = "hello"; //为字符串常量,存在于静态存储区。所以试图改变*p的操作都会失败。
char p[] = "hello"; //存在栈空间,函数结束就释放了。
char *p = "hello"; //为字符串常量,存在于静态存储区。所以试图改变*p的操作都会失败。
上一篇:没有了
下一篇:Linux系统下emacs基本操作(20130707-1700更新)
下一篇:Linux系统下emacs基本操作(20130707-1700更新)