个人C语言的一些盲区
标签: C/C++
1.
学习前辈的一个bug,在注释一行后的末尾不能加‘\’,‘\’的意思是该行没结束,则注释会把下一行也注释掉,但是软件不会显示下一行被注释了。例如:
main()
{
// this is a comment and with a endding of \
other_codding();
}
这个程序的注释(第一行)将第二行的函数也一起注释了,但是软件没有用颜色标示下边也被注释。
2.
单片机软件编译过程中有这么个问题,我用的是CCS,当你写如下代码:
main()
{
int a=0;
while(1)
{
a = a + 1;
}
}
软件在编译时会将“a = a + 1;”这句话直接忽视掉,不编译。原因是a的变化并未对单片机产生任何影响,只对本身产生影响,所以不编译,被优化掉。
3.
在程序for循环中,递减循环要比递增循环更好一些,适应递减,更容易被操作系统或单片机监测。
main()
{
int a;
for(a=100;a>0;a--); //better
}
4.
C语言在同一运算符中的多个操作数之间未规定计算顺序(&&、||、?:和,运算符除外),所以可能会出现错误。
printf("%d %d\n",++n, power(2,n));
在这个运算中,可能先计算++n,再调用power(),也可能先调用power(),在计算++n。所以会出现错误。再如:
x = acc() + mic();
在这个运算中,可能先调用acc(),再调用mic(),或者相反,如果两个函数之间存在互相的全局参数调用修改,可能会出现错误。
5.
将外部变量的声明与定义严格区分开来很重要。变量声明用于说明变量的属性(主要是变量的类型),而变量定义除此之外还将引起存储器的分配。
int sp;
double val [MAXVAL];
extern int sp;
extern double val []
前边两条语句是变量定义,会为之分配存储单元,同时这两条语句为该源文件中其余部分的声明。
后边两条语句声明外部变量,val 数组的长度在其他地方确定。
6.
static关键字可以用于声明外部变量、函数或内部变量。当static用于声明外部变量时,这样的变量将不能被同一程序的其他文件所访问,而只能被被声明的该文件内的函数所访问,起到隐藏外部变量的功能。例如:当file.c文件中声明了两个外部变量与函数,若想只允许该函数使用这两个外部变量而不允许main.c文件使用,则可以将这两个外部变量声明为静态变量,这样这两个外部变量将只对于该文件内有效。
同理,static也可以用于声明函数。通常来说,函数是可以全局访问的,如果把函数声明为static类型,则该函数只在该函数声明所在的文件内可见,在其他文件内均无法访问。
当static用于声明内部变量时,则该变量只能在该函数中有效,但它与自动变量不同的是,不管函数是否存在,它将始终占用内存,不会随着函数被调用与退出而存在或消失。
static修饰内部静态变量时的作用域也在函数内部,虽然函数调用结束不会被销毁,但静态变量在函数之外不可见。
7.
自动变量,是指在定义它们时才创建,在定义它们的函数返回时系统将回收该变量所占用的内存空间。一般,不做专门说明的局部变量都是自动变量,用auto关键字说明,可省略。自动变量只有一种存储方式,就是存储在栈中,所以它的作用域只在函数内。
8.
宏定义的两个不清楚的地方:①宏定义中的形式参数不能用带引号的字符串替换。如:
#define f(b) printf("b" "%d",b)
b参数将只替换printf函数中第二个b;如果必须要替换,则在替换的文本行中,参数以#作为前缀,例如:
#define f(b) printf(#b "%d", b)
这样,当使用语句f(mm)
调用该宏时,将被扩展为:
printf("mm" "%d", mm)
②预处理运算符##
为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与##
相邻,则该参数将被实际参数替换,##
与前后的空白符将被删除,并对替换后的结果重新扫描。如,使用paste
连接两个参数:
#define paste(front, back) front ## back
当使用past(name, 1)
宏调用时,结果将是name1