深入理解C语言

 

1、关于scanf函数输入双精度实型数据时的问题

 1 //关于double类型的变量的一些小问题
 2 #include<stdio.h>
 3 int main(){
 4     double m,n;
 5     printf("enter m and n:");
 6     //用scanf函数输入双精度实型数据时,不能用"%f"格式声明,而应当用"%lf"格式声明
 7     scanf("%f%lf",&m,&n);
 8     //用printf函数输出双精度实型数据时,"%f"与"%lf"两种格式声明均可
 9     printf("m=%lf\nn=%lf\n",m,n);
10     printf("m=%f\nn=%f\n",m,n);
11     return 0;
12 }

代码运行结果

 

2、因循环变量引起的运算结果错误,此错误特别隐蔽。

     当循环变量赋初值时,有多个变量设置初值时,最前面一个变量第一次定义时,后面的变量也默认定义为第一次定义,全部为局部变量。

 1 //用数组输入三个数,用函数来计算其中最大值,并输出这个数是第几个数
 2 #include<stdio.h>
 3 int main(){
 4     int max(int x,int y);
 5     int a[3],m,n;
 6     printf("enter 3 numbers:");
 7     for(i=0;i<3;i++){
 8         scanf("%d",&a[i]);
 9     }
10 
11     //在此处将循环变量定义为局部变量引起后面的m与n也变为局部变量,引起运算结果错误
12     //在此处应特别注意,此错误特别隐蔽
13   //如果在此处初始化变量,m与n也默认为新的局部变量,循环结束后的第20行打印语句中的m与n不是for循环中的数值
14     for(int i=1,m=a[0],n=0;i<3;i++){
15         if(max(m,a[i])>m){
16             m=max(m,a[i]);
17             n=i;
18         }
19     }
20     printf("The largest numberr is %d\nit is the %dth number.\n",m,n+1);
21 }
22 int max(int x,int y){
23     return (x>y?x:y);
24 }

代码运行结果

 

3、数组名作函数参数时,只需在实参位置写上数组名即可。

 1 //有一个一维数组score,内放10个学生成绩,求平均成绩
 2 #include<stdio.h>
 3 int main(){
 4     double average(double array[10],int n);
 5     double score[10],ave;
 6     printf("enter 10 student socre:");
 7     for(int i=0;i<10;i++){
 8         scanf("%lf",&score[i]);
 9     }
10     //将数组名作为函数参数时,只需将数组名放在相对应的位置即可
11     //若写成"score[10]",引用的将不是score数组,而是数组元素socore[10]
12     ave=average(score[10],10);
13     printf("10个学生的平均成绩是%f",ave);
14 }
15 double average(double array[10],int n){
16     double ave,sum=0;
17     for(int i=0;i<n;i++){
18         sum+=array[i];
19     }    
20     ave=sum/n;
21     return ave;
22 }    

代码运行结果

 

4、多维数组作函数参数时,第1维的大小可以省略,第2维的大小不可以省略,并且实参与形参的维数要相同。

 1 //有一个3*4的矩阵,求所有元素中的最大值
 2 #include<stdio.h>
 3 int main(){
 4     //把二维数组名作函数参数时,第二维的大小不能省略,调用函数时不加函数的维数,只写函数名
 5     int max(int array[][4],int x,int y);
 6     int a[3][4]={{3,2,4,7},{12,8,9,20},{21,28,31,87}};
 7     printf("The max=%d",max(a,3,4));
 8 }
 9 int max(int array[][4],int x,int y){
10     int i,j,max=array[0][0];
11     for(i=0;i<x;i++)
12         for(j=0;j<y;j++)
13             max=array[i][j]>max?array[i][j]:max;
14     return max;
15                 
16 }

 

 5、循环条件表达式用指针来进行判断,造成地址无限越界,无法跳出循环

 1 //用指针来实现选择排序
 2 #include<stdio.h>
 3 int main(){
 4     void sort(int *x,int n);
 5     int a[10]={2,4,9,5,8,1,0,3,7,6};
 6     int *pa=a;
 7     int n=10;
 8     sort(pa,n);
 9     //用指针输出数组时一定要先执行"pa=a",此程序中不执行此句也可以正确输出,在有的程序中执行到此句时指针pa已经指向了其他位置,需要对指针复位
10     //此句中的循环条件表达式不能使用"pa<pa+10"来判断,这是因为步长表达式执行"pa++"操作,每一次执行完步长表达式之后再执行循环条件表达式时pa的值都会改变,"pa<pa+10"将一直满足条件,无法跳出循环,这一点一定要注意,千万要小心使用
11     for(pa=a;pa<pa+n;pa++)
12         printf("%d  ",*pa);    
13 }
14 void sort(int *x,int n){
15     int temp;
16     int *pi,*pj,*pn;
17     pi=x;
18     pn=x+n;
19     for(pi;pi<pn-1;pi++){
20         for(pj=pi+1;pj<pn;pj++){
21             if(*pi>*pj){
22                 temp=*pi;*pi=*pj;*pj=temp;
23             }
24         }
25     }
26 }

代码运行结果

说明:在gcc编辑器里会自动停止不再访问后续的地址,在VS里程序是无法自动停止的,在逻辑上程序是不会自动停止。

 

6、用函数调用实现字符串的复制,误用指针来存放字符型数组

 

 1 //用函数调用实现字符串的复制,误用指针来存放字符型数组
 2 #include<stdio.h>
 3 int main(){
 4     void copy_string(char *from,char *to);
 5     //字符指针a、b分别指向两个字符串常量
 6     char *a="I am a teacher!";
 7     char *b="You are a student!";
 8     printf("%s\n%s\n",a,b);//此句可以正常输出
 9     //在此处不可以这样使用函数copy_string将指针指向的内容复制到另一个指向字符串常量的字符指针
10     //这是因为指针只是一个变量,其下一个指向的内容是不确定,不是"i+1".只有数组开辟了一段连续的内存空间,用指针才可以指向其下一个地址.
11     //字符型指针只是一个单位的指针变量,所以就不能用来存放一个字符型数组的内容了.其实最根本的原因是因为字符型指针变量不能存放字符型的变量.
12     copy_string(a,b);//在此处还有一个风险,因为下一个指针是随机的,如果函数中形参*from++若不是'\0',则无法结束for循环语句.
13     printf("%s\n%s\n",a,b);//此句不能正常输出.
14 }
15 //将两个数组名的地址(实参)传给指针指针(形参)
16 void copy_string(char *from,char *to){
17     for(;*to++=*from++;);
18 }

 

 运行结果:

 

posted @ 2018-07-14 11:28  张子游zy  阅读(253)  评论(0编辑  收藏  举报