C语言中要注意的一些问题
下面列出了一些C语言中常见的问题和注意事项,跟考试无关,有些表达不是很严格,仅供辅助学习。
1、 C语言中规定,每条语句结束时末尾加分号,而不是每行末尾加分号!
2、 在用scanf和printf函数输入和输出时,一定要记得int跟%d对应,long跟%ld对应,float
和double跟%f对应,否则不能正确输入和输出数据。
3、 使用scanf函数时,在双引号中最好只出现各种格式控制符,如”%d%d%f%c”,而不要
随意增加其它字符,以免画蛇添足,增加输入的麻烦。
4、 通过scanf(“%s”,字符数组名)和gets(字符数组名)都可以输入一个字符串,并将
其存储在指定的字符数组中。区别在于,前者当输入字符中遇到空格就认为输入结束,后者则可以接收包含空格的字符串。
5、 在数值运算时,要注意防止数据的溢出。特别是int类型数值范围较小,比较容易溢出。
一旦溢出,结果出错。
6、 要注意各种运算符的优先级,需要时可以加()来保证运算顺序满足要求。
7、 参加关系和逻辑运算的数据可以是任意类型和任意值,计算机将所有非零数理解为1
(真),而0则为假,然后进行运算。得到的结果只有两种,要么是1,要么是0。
8、 整数的比较可以使用关系运算;浮点型数据在比较是否相等时,一般这样实现 fabs(表达式或变量)<=1e-6
而字符串比较必须通过strcmp函数实现。
9、 strcpy(字符数组1,字符数组2或字符串常量)的功能相当于
字符数组1=字符数组2或字符串常量 (程序中绝对不能写成这样!)
10、 变量和数组在定义时若未赋初值(未初始化),则其内容是随机数(不确定)。数组
若是部分初始化,则未指定初值的数组元素自动赋值为0(也可以理解为字符’\\0’)
11、 for循环非常常用,要注意后面括号中三个表达式的执行顺序。若非必要,最好不
要省略三个表达式。若循环体多于一条语句,必须用{}将它们括起来,变成语句块。(对于while和do..while循环也是这样)
12、 数组元素是一个挨一个放在内存一片连续的空间中。对于多维数组,则采用行主序
组织存放。比如二维数组arr[M][N],看作有arr[0], arr[1], …, arr[M-1]个一维数组,每个一维数组有N个元素 arr[0][0], arr[0][1], …, arr[0][N-1] ←第0行 arr[1][0], arr[1][1], …, arr[1][N-1] ←第1行 ...
arr[M-1][0], arr[M-1][1], …, arr[M-1][N-1] ←第M-1行 首先存放第0行元素,接着是第1行,??。 二维数组实际上也可以形象地看作一张二维表格。
13、 单个数组元素就是一个独立的变量,只是访问时应该写成
数组名[下标]
下标可以是常量、变量或表达式(当然表达式的结果应该是整数),第一个数组元素下标必定为0。编译器不对下标越界(下标值超出数组定义的大小),须程序设计者自己保证。
14、 若要逐个访问数组中的每个元素,一般通过循环(常用for)。一维数组用一重循环,
二维数组用二重循环,以此类推。比如对于二维数组arr[M][N] for ( i=0; i 维数组的第i行*/ for( j=0; j 组的第j列*/ arr[i][j]=…; /*访问数组中的某个元素*/ 当然,调换一下,外循环控制列,内循环控制行也是可以的,完全看你的需要。 15、 函数 16、 一个C程序可以由多个文件组成,每个文件包含若干个函数,其中只能有一个main 函数。各个函数可以相互调用,甚至自我调用(即递归调用),但不能调用main函数。计算机一定从main函数开始执行(实际上就是操作系统调用main函数),最终在main函数结束。 17、 函数也有类型,称函数类型,实际上是指该函数返回值的类型。当确定一个函数没 有返回值时,最好指定函数类型为void,否则默认类型为int,容易造成误解。 18、 函数调用和返回时,若类型不一致,计算机会做自动类型转换。例如: int fun( float a){ float x; ?? return x; /*由于函数类型为int,而x是float,因此计算机自动将float转换为int,然后将结果送回主调函数(这里是main函数)*/ main(){ int a; long b; ?? b=fun(a); /*实参a的类型为int,而形参类型为float,当实参赋给形参时,自动类型转换int?float;当fun函数返回时,返回值为int,而b是long,赋值时又自动进行类型转换*/ 在实际应用当中,要注意高精度数据类型向的低精度数据类型转换时,可能造成精度损失甚 至数据溢出。 19、 无论如何,在函数调用时,实参将值赋给形参,也就是说,形参得到的是实参的复 制品,它们是互不相干的。任何时候都不要企图通过改变形参的值而去影响实参的值!.. 也许你会指出,我把数组名作为参数传递时,那调用函数后,数组的内容不是就发生变...化了吗?不要有这样的误解!(详见第20点) 20、 习惯上,我们通常在文件的最开头进行函数的声明(也就是写出函数的原型),顺 序如下: 假设这是一个名称为abc.c的C源程序文件 #include “stdio.h” /*开始先是库函数的声明,这可以通过include包含相应头文件即可*/ #include “math.h” #include “string.h” ?? int fun1(float, int); /*接下来是自己的函数声明,注意不要遗漏了结尾的分号。当然也可以将这些声明单独放在另一个文件中(一般文件扩展名为.h,以示区别),然后在这里也是include进来*/ void fun2(long); int * fun3(int [] ); ?? 21、 在函数内部定义的变量称为“局部变量”,一般在函数最开始处统一定义,仅在本 函数内部有效;在函数外部定义的变量称为“全局变量”(或外部变量、全程变量),一般在文件最开始处定义,对于本文件中所有函数都有效,但尽量限制(少用)全局变量。当全局变量与局部变量同名时,在局部变量作用范围内,全局变量被屏蔽。 指针 22、 指针就是地址。若用一个变量来存储地址,那么这个变量称为指针变量。指针变量 也有类型。指针变量只能存放地址(指针),也就是说要么通过&运算符将某个变量(同类型的)的地址赋予指针变量,要么将另一个指针变量(同类型的)的值赋予它。例如下面的语句是正确的。 int a, *p, *q; p=&a; /*赋值后,我们称指针变量p指向变量a*/ q=p; 23、 当定义了指针变量后,应明确给它赋值,否则该指针变量“悬空”,很容易导致程 序运行异常。这种情况在编译时会有警告,应当注意。 24、 假如某个函数中定义了一些变量,希望通过调用另一个函数后这些变量的值发生变 化,必须这样设计: ①. 主调函数将这些变量的地址作为实参传递给被调函数; .. ②. 被调函数用指针变量作为形参接收传过来的地址; ③. 在被调函数中通过地址去改变相应内存单元的内容。 25、 数组名是指针常量,它永远指向该数组第一个元素(数组的起始地址)。 26、 当数组名作为参数传递时,实际上传的是数组的首地址。如: main(){ int a[10]; ?? func( a, 10 ); /*函数调用时,形参p得到实参a的值*/ ?? } void func( int *p, int n){ p++; /*形参p的值发生变化,但实参a的值不会变化。而且a是指针常量,也不可能发生变化*/ *p=254; /*a[1]的值变化了。这是由于此时p的值是a[1]的地址,计算机根据该地址对相应内存单元进行赋值。*/ 27、 假设p是指针变量,它的值是2000。那么p++或p--后,p是指向后一个(或前一 个)数据,也就是说计算机会根据指针变量的类型,自动调整跳过的内存单元数,这也是指针变量为什么要定义类型的原因之一。因此,利用指针对数组进行操作可以达到通过数组下标访问数组元素同样的效果,而且效率更高。 下面两段程序效果一样 int a[N]; for( i=0; i int a[N]; int *p; p = a; /*指针变量定义后必须赋值,否则悬空*/ for( i=0; i 28、 多维数组的指针的确比较难懂,下面以二维数组为例说明 int a[10][5]; int i,j,*k,*p; p=&a[0][0];k=p; for(i=0;i<10;i++) for(j=0;j<5;j++) {if (*k<*p) k=p;p++;}
相关推荐: