欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言使用注意事项(一)

程序员文章站 2022-07-07 11:20:07
...


原创作品,转载请表明http://blog.csdn.net/yming0221/article/details/7233564

更多查看

C语言使用注意事项(二)

C语言使用注意事项(三)

C语言使用注意事项(四)

1、getchar()函数的使用方法

getchar()返回值为int型,如下使用方法不正确

#include <stdio.h>

int main()
{
        
        char tmp;
        while( (tmp=getchar())!=EOF )
        {
                printf("%c",tmp);
        }
        return 0;
}
当EOF的宏定义超出char型数据所表示的范围时,这样就会出错,这种错误很难预料。

char的取值范围究竟是[-128,127]还是[0-255]取决于编译器。GCC编译器中的char表示signed char。

所以应该将tmp的类型改成int 型,防止出现错误。


2、全局变量的使用方法

cfaq.h

#ifndef _CAFQ_H
#define _CAFQ_H

//DEFINE(int, ex);
extern int ex;

void print();
#endif

cfaq.c

#include "cfaq.h"
int ex;
void print()
{
        printf("%d\n",ex);
}

main.c

#include <stdio.h>
#include "cfaq.h"
int ex=3;
int main(int argc,char **argv)
{
        print();
        return 0;
}


3、extern关键字使用

声明变量extern修饰的表示全局变量

而修饰函数时有无extern修饰无实质差别


4、使用typedef声明复杂的声明
下面首先使用typedef声明大小为N的指向字符的指针的函数的指针的数组

typedef char *pc;//定义一个字符指针

typedef pc fpc();//定义一个返回字符指针的函数

typedef fpc *pfpc;//定义一个指向fpc()函数的函数指针

typedef pfpc fpfpc();//返回上述函数指针的函数

typedef fpfpc *pfpfpc;//上述函数的指针

pfpfpc a[N];//定义一个上面函数指针的数组

相当于下面一句话

char *(*(a[N])())();


5、main()函数的正确定义

main()函数必须声明为int main()或int main(void)或int main(int argc,int **argv)

不能定义为void main(){ }以消除无返回值警告,但是它可能导致与调用者期待的返回顺序不能的返回顺序


6、char a[]="String"和char *a="String"初始化字符串的区别

第一种方法初始化之后可以修改a[i]的值,第二种无法修改a[i]的值,其存储空间是只读的,当修改时出现错误。


7、C中参数传递的方式

C中确实没有按引用传递的参数传递方式。

严格地讲, C 总是按值传递。你可以自己模拟按引用传递, 定义接受指针的函数, 然后在调用时使用 & 操作符。事实上, 当你向函数传入数组 (传入指针的情况参见问题 6.4 及其它) 时, 编译器本质上就是在模拟按引用传递。但是 C 没有任何真正等同于正式的按引用传递或 C++ 的引用参数的东西。另一方面, 类似函数的预处理宏可以提供一种“按名称传递”的形式。


8、有关i++的定义

int i=3;

printf("%d",(i++)*(i++));我的编译器输出结果是9,而不是12。原因尽管后缀自加和后缀自减操作符 ++ 和 -- 在输出其旧值之后才会执行运算,但这里的“之后”常常被误解。没有任何保证确保自增或自减会在输出变量原值之后和对表达式的其它部分进行计算之前立即进行。也不能保证变量的更新会在表达式 “完成”之前的某个时刻进行。本例中, 编译器选择使用变量的旧值相乘以后再对二者进行自增运算。


9、*p++的含义是自增指针p,还是自增p的内容

*p++和*(p++)等价,++和--比前缀的一目操作运算符优先级高,它的含义是自增p并返回p增加前地址的内容。所以如果自己比较混淆,干脆使用括号消除自己的歧义。


10、左值与右值

顾名思义,左值就是只能出现在=号的左边,可以被赋值;右值是只能出现在=号的右端,不能被赋值也不能自增;

例如下面一个char *的指针恰好指向一个int型数据,要想对其做自增运算。

那么下面的代码正确吗?

((int *)p)++

答案是否定的,由于(int *)p是经过类型转换得到的,由于类型转换就是将部分二进位看作其他类型,并做相应的对待。数据类型转换所产生的是一个右值(R-value),故不能对其进行修改和自增操作。

下面是GCC 4.5下的编译出错信息

C语言使用注意事项(一)