机试记不住头文件_朱兆祺教你如何攻破C语言学习、笔试与机试的难点
第四节关键字、运算符与语句
1.1static
1. 如程序清单4. 1所示,请问输出i、j的结果?
程序清单4. 1 static
#include
static int j ;
void fun1(void)
{
static int i = 0 ;
i++ ;
printf("i = %d " , i );
}
void fun2(void)
{
j = 0 ;
j++ ;
printf("j = %d \n" , j );
}
int main(int argc, char *argv[])
{
int k = 0 ;
for( k = 0 ; k < 10 ; k++ ){
fun1() ;
fun2() ;
printf("\n");
}
return 0;
}
答案:
i = 1 j = 1
i = 2 j = 1
i = 3 j = 1
i = 4 j = 1
i = 5 j = 1
i = 6 j = 1
i = 7 j = 1
i = 8 j = 1
i = 9 j = 1
i = 10 j = 1
请按任意键继续. . .
很多人傻了,为什么呢?是啊,为什么呢?!
由于被static修饰的变量总存在内存静态区,所以运行这个函数结束,这个静态变量的值也不会被销毁,函数下次使用的时候仍然能使用这个值。
有人就问啊,为什么j一直是1啊。因为每次调用fun2()这个函数,j都被强行置0了。
static的作用:
(1) 函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次, 因此其值在下次调用时仍维持上次的值;
(2) 在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3) 在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明 它的模块内;
(4) 在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5) 在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。
1.2for循环的深究
1.如程序清单4. 2所示,输出结果是什么?
程序清单4.2 for循环
#include
int main(int argc, char *argv[])
{
int i = 0 ;
for( i = 0 ,printf("First = %d " , i ) ;
printf("Second = %d " , i ) , i < 10 ;
i++ , printf("Third = %d " , i ))
{
printf("Fourth = %d \n" , i) ;
}
return 0;
}
这个题目主要考察对for循环的理解。我们先来看看运行程序会输出什么?
First = 0 Second = 0 Fourth = 0
Third = 1 Second = 1 Fourth = 1
Third = 2 Second = 2 Fourth = 2
Third = 3 Second = 3 Fourth = 3
Third = 4 Second = 4 Fourth = 4
Third = 5 Second = 5 Fourth = 5
Third = 6 Second = 6 Fourth = 6
Third = 7 Second = 7 Fourth = 7
Third = 8 Second = 8 Fourth = 8
Third = 9 Second = 9 Fourth = 9
Third = 10 Second = 10 请按任意键继续. . .
从输出我们就可以知道程序到底是什么运行:
首先i = 0 , 所以输出:First = 0 ; 接着输出:Second = 0 ; i < 10 成立,则输出:Fourth = 0 。就此完成第一个循环。接着 i ++ , 此时i = 1 ,输出:Third = 1 ;接着输出:Second = 1 ;i < 10 成立,则输出:Fourth = 1 ······以此类推。
1.3尺子——sizeof
1. 如程序清单4. 3所示,sizeof(a),sizeof(b)分别是多少?
程序清单4.3 sizeof
#include
int main(int argc, char *argv[])
{
char a[2][3] ;
short b[2][3] ;
printf( "sizeof(a) = %d \n" , sizeof( a ) ) ;
printf( "sizeof(b) = %d \n" , sizeof( b ) ) ;
return 0;
}
这个题目比较简单,由于char 是1个字节、short是2个字节,所以本题答案是:
sizeof(a) = 6
sizeof(b) = 12
请按任意键继续. . .
好的,再来看看如程序清单4. 4所示,sizeof(a),sizeof(b)分别是多少?
程序清单4. 4 sizeof
#include
int main(int argc, char *argv[])
{
char *a[2][3] ;
short *b[2][3] ;
printf( "sizeof(a) = %d \n" , sizeof( a ) ) ;
printf( "sizeof(b) = %d \n" , sizeof( b ) ) ;
return 0;
}
是数组指针呢,还是指针数组呢?这里涉及*和[]和优先级的问题。我告诉大家的是这两个数组存放的都是指针变量,至于为什么,在后续章节会详细解释,然而指针变量所占的字节数为4字节,所以答案:
sizeof(a) = 24
sizeof(b) = 24
请按任意键继续. . .
1.4++i和i++
1. 或许大家都知道,++i是先执行i自加再赋值,但是i++是先赋值再自加,但是还有隐藏在后面的东西呢?
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (++i) + (++i) ;
C-Free编译输出是:7,有的编译器输出是:9。这两个答案都是对的,编译器不同所不同。7 = 2+2+3;9=3+3+3。区别在于答案是7的先执行(++i)+(++i)再执行+(++i),但是答案是9的是一起执行。
这只是前奏,先看几个让你目瞪口呆的例子。编译环境是VS2010。
int i = 0 ;
int iNumber = 0 ;
iNumber = (i++) + (++i) + (++i) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:4!!!4 = 1+1+2。
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (i++) + (++i) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:4!!!4=1+1+2。
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (++i) + (i++) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:6!!!6=2+2+2。
这里至少能说明两个问题,其一,先执行前面两个,再执行第三个;其二,(i++)这个i的自加是最后执行!
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (i++) + (++i) + (++i) + (i++) ;
printf( "iNumber = %d \n" , iNumber ) ;
这个会是多少?!答案是:10!!!10=1+1+2+3+3!
不同的编译器或许会存在不同的答案,希望读者自行进行验证。
1.5scanf()函数的输入
1. 如程序清单4. 5所示,运行程序,当显示Enter Dividend: , 输入的是a,按下Enter之后程序会怎么运行?
程序清单4.5 scanf()函数的输入
#include
int main(void)
{
float fDividend,fDivisor,fResult;
printf("Enter Dividend:");
scanf("%f",&fDividend);
printf("Enter Divisor:");
scanf("%f",&fDivisor);
fResult=fDividend/fDivisor;
printf("Result is: %f\n",fResult);
return 0;
}
这个问题有人会说,肯定是显示Enter Divisor:要我输入除数咯。是这样吗?
答案是:如果你在Enter Dividend:之后输入非数字,按下Enter之后显示的不是Enter Divisor: 要你输入除数,而是程序到此就运行结束,显示一个不确定答案,这个答案每一次都会变。如果你在Enter Divisor:之后输入非数字,按下Enter之后显示的不是Reslut的结果, 而是程序到此就运行结束,显示一个不确定答案,这个答案每一次都会变。
由于scanf()使用了%f,当输入数字的时候,scanf()将缓冲区中的数字读入fDividend,并清空缓冲区。由于我们输入的并非数字,因此scanf()在读入失败的同时并不会清空缓冲区。最后的的结果是,我们不需要再输入其他字符,scanf()每次都会去读取缓冲区,每次都失败,每次都不会清空缓冲区。当执行下一条scanf()函数读取除数时,由于缓冲区中有数据,因此它不等待用户输入,而是直接从缓冲区中取走数据。
那么防止输入非数字的程序应该怎样呢?
#include
int main( int argc , char *argv[] )
{
float fDividend , fDivisor , fResult ;
int iRet ;
char cTmp1[ 256 ] ;
printf( "Enter Dividend \n" ) ;
iRet = scanf( "%f" , &fDividend ) ;
if ( 1 == iRet )
{
printf( "Enter Divisor \n" ) ;
iRet = scanf( "%f" , &fDivisor ) ;
if ( 1== iRet )
{
fResult = fDividend / fDivisor ;
printf( "Result is %f \n" , fResult ) ;
}
else
{
printf( "Input error ,not a number! \n" ) ;
gets(cTmp1) ;
return 1 ;
}
}
else
{
printf( "Input error , not a number! \n" ) ;
gets(cTmp1) ;
return 1 ;
}
return 0 ;
}
1.6scanf()函数的返回值
1.如程序清单4. 6所示,请问输出会是什么?
程序清单4. 6 scanf()函数的返回值
inta , b ;
printf("%d \n", scanf("%d%d", &a , &b) ) ;
输出输入这个函数的返回值?!答案是:2。只要你合法输入,不管你输入什么,输出都是2。那么我们就要深入解析scanf这个函数。scanf()的返回值是成功赋值的变量数量。
1.7const作用下的变量
1.阅读如程序清单4. 7所示,想想会输出什么?为什么?
程序清单4. 7 const作用下的变量
constintiNumber = 10 ;
printf(" iNumber = %d \n",iNumber) ;
int*ptr = (int*)(&iNumber) ;
*ptr = 100 ;
printf(" iNumber = %d \n",iNumber) ;
const的作用在第四章已经详细讲了,这里就不再累赘,答案是:10,10。这里补充一个知识点:
const int *p 指针变量p可变,而p指向的数据元素不能变
int* const p 指针变量p不可变,而p指向的数据元素可变
const int* const p 指针变量p不可变,而p指向的数据元素亦不能变
1.8*ptr++、*(ptr++),*++ptr、*(++ptr),++(*ptr)、(*ptr)++的纠缠不清
1.如程序清单4. 8所示程序,输出什么?
程序清单4.8 *ptr++
intiArray[3] = { 1 , 11 , 22} ;
int*ptr = iArray ;
printf("*ptr++ = %d \n", *ptr++ ) ;
printf("*ptr = %d \n", *ptr) ;
纠结啊,是先算*ptr还是ptr++;还是纠结啊,ptr是地址加1还是偏移一个数组元素!
这里考查了两个知识点,其一:*与++的优先级问题;其二,数组i++和++i的问题。*和++都是优先级为2,且都是单目运算符,自右向左结合。所以这里的*ptr++和*(ptr++)是等效的。
首先ptr是数组首元素的地址,所以ptr++是偏移一个数组元素的地址。那么ptr++运算完成之后,此时的ptr是指向iArray[1],所以第二个输出*ptr = 11 。如图4. 1所示。那么倒回来看第一个输出,ptr++是在执行完成*ptr++之后再执行的,所以,*ptr++ = 1 。
图4.1 ptr++
如程序清单4. 9所示程序,输出会是什么?
程序清单4.9 *++ptr
intiArray[3] = { 1 , 11 , 22} ;
int*ptr = iArray ;
printf("*++ptr = %d \n", *++ptr ) ;
printf("*ptr = %d \n", *ptr) ;
这个解释和上面解释差不多,就是++ptr和ptr++的差别,所以这里的两个输出都是:11。同样的道理,*++ptr和*(++ptr)是等效。
再如程序清单4. 10所示,输出又会是什么?
程序清单4.10(*ptr)++
intiArray[3] = { 1 , 11 , 22} ;
int*ptr = iArray ;
printf("(*ptr)++ = %d \n", (*ptr)++ ) ;
printf("*ptr = %d \n", *ptr) ;
这个的输出是:1,2。原因请读者分析。
机试记不住头文件_朱兆祺教你如何攻破C语言学习、笔试与机试的难点相关推荐
- 机试记不住头文件_计算机考研机试攻略
目录 写在前面的话 2 关于N诺 4 如何使用本书? 5 第一章 从零开始 8 1.1机试分析 8 1.2 IDE的选择与评测结果 10 1.3 DreamJudge的使用 11 1.4输入输出技巧 ...
- 攻破c语言笔试与机试难点,如何攻破C语言学习、笔试与机试的难点.doc
如何攻破C语言学习.笔试与机试的难点 第一节??C语言编程中的几个基本概念1.1? ?? ?#include< >与#include" "? 1.? ?#include ...
- java反射头文件_编程基础知识——C++能不能支持Java和ObjC的反射?
C++能不能支持Java和ObjC的反射? 要回答这个问题.首先我们要清楚什么是反射.什么是反射? 教科书的解释我就不说了,(^o^)事实上我也记不得.实际开发应用的反射就是在没有某个类型的头文件或者 ...
- 单片机sleep函数的头文件_单片机代码模块化设计思想浅谈
前言:前段时间分享的文章[单片机裸机代码框架设计思路],很多读者给我留言,觉得很不错,对于初学者而言,这是一个进阶的技巧,对于我而言,这是对自己总结和表达能力的一个提升. 本文章我们再谈谈单片机代码的 ...
- 单片机sleep函数的头文件_单片机学习day8—单片机IO扩展
74HC165芯片-并转串 74HC165中文资料.pdf 267.6K · 百度网盘 8位移位寄存器(并行输入,互补串行输出) 时钟输入端 CLK,CLK INK (上升沿有效) A-H 并行数据输 ...
- c++ string 头文件_“延期不延学” 第25期 | C++篇 | C/C++常用函数
在c/c++的课程和课设中,函数的应用都是至关重要的,这里就为大家收集整理了c/c++常用的一些函数,希望大家多加应用以熟练. 1.字符处理函数 本类别函数用于对单个字符进行处理,包括字符的类别测试和 ...
- c++ max 的头文件_学用C/C++编写小游戏程序(2.2 打字练习游戏)
2.2 打字练习游戏(随机数与特殊输入) 有了上面的绘制简单动画的技术,现在来看一下简易的打字练习游戏. [程序2-2]编写一个简易的打字训练游戏:计算机每次随机生成一个小写英文字符,从屏幕一行的左侧 ...
- java 输入输出头文件_引入的标准头文件与标准输出以及FOR循环
感觉C学了一遍又一遍,大学学过,工作的时候也学过,奈何一直在弄JAVA,没有怎么用过C,学了就忘,忘了就....算了-- 现在搞音视频开发,又必须弄到这一块了.因此,写点东西回加强记忆.是的,基础本来 ...
- bool类型头文件_[C++基础入门] 2、数据类型
点击上方 蓝字 关注我呀! [C++基础入门] 2.数据类型 文章目录 2 数据类型 2.1 整型 2.2 sizeof关键字 2.3 实型(浮点型) 2.4 字符型 2.5 转义字符 2.6 字符串 ...
最新文章
- Segmentation fault到底是何方妖孽
- 一篇文章教你弄懂java CMS垃圾回收日志
- Item9:总是要改写toString
- Flask 应用的文件结构
- 高颜值可定制在线绘图工具
- 关于python中字典描述正确的是_python总结七
- 服务器linux什么镜像好用,Linux系统镜像建站Debian和Ubuntu选择哪个比较好
- GreenSock GSAP 3.0 最新版 所有内容创建于2020年4月4日
- 记录一下postman汉化踩过的坑
- 数学物理计算机的思考
- spring cloud day(6) gateway网关
- Unity 之 2D水插件推荐和模拟水效果制作分享
- 日记20050930
- Windows 10 显示桌面图标 计算机 / 此电脑 / 我的电脑
- 腾讯游戏助手运行闪退日志查看
- 实战分享:一文读懂RS-232总线
- 微型四轴DIY机架,轻巧稳固耐摔,通用720空心杯电机,9厘米轴距
- 数学家的情书-笛卡尔的心型线方程
- onReachBottom无法触发也不报错
- matlab生成一个数值一样的向量