第四节关键字、运算符与语句

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语言学习、笔试与机试的难点相关推荐

  1. 机试记不住头文件_计算机考研机试攻略

    目录 写在前面的话 2 关于N诺 4 如何使用本书? 5 第一章 从零开始 8 1.1机试分析 8 1.2 IDE的选择与评测结果 10 1.3 DreamJudge的使用 11 1.4输入输出技巧 ...

  2. 攻破c语言笔试与机试难点,如何攻破C语言学习、笔试与机试的难点.doc

    如何攻破C语言学习.笔试与机试的难点 第一节??C语言编程中的几个基本概念1.1? ?? ?#include< >与#include" "? 1.? ?#include ...

  3. java反射头文件_编程基础知识——C++能不能支持Java和ObjC的反射?

    C++能不能支持Java和ObjC的反射? 要回答这个问题.首先我们要清楚什么是反射.什么是反射? 教科书的解释我就不说了,(^o^)事实上我也记不得.实际开发应用的反射就是在没有某个类型的头文件或者 ...

  4. 单片机sleep函数的头文件_单片机代码模块化设计思想浅谈

    前言:前段时间分享的文章[单片机裸机代码框架设计思路],很多读者给我留言,觉得很不错,对于初学者而言,这是一个进阶的技巧,对于我而言,这是对自己总结和表达能力的一个提升. 本文章我们再谈谈单片机代码的 ...

  5. 单片机sleep函数的头文件_单片机学习day8—单片机IO扩展

    74HC165芯片-并转串 74HC165中文资料.pdf 267.6K · 百度网盘 8位移位寄存器(并行输入,互补串行输出) 时钟输入端 CLK,CLK INK (上升沿有效) A-H 并行数据输 ...

  6. c++ string 头文件_“延期不延学” 第25期 | C++篇 | C/C++常用函数

    在c/c++的课程和课设中,函数的应用都是至关重要的,这里就为大家收集整理了c/c++常用的一些函数,希望大家多加应用以熟练. 1.字符处理函数 本类别函数用于对单个字符进行处理,包括字符的类别测试和 ...

  7. c++ max 的头文件_学用C/C++编写小游戏程序(2.2 打字练习游戏)

    2.2 打字练习游戏(随机数与特殊输入) 有了上面的绘制简单动画的技术,现在来看一下简易的打字练习游戏. [程序2-2]编写一个简易的打字训练游戏:计算机每次随机生成一个小写英文字符,从屏幕一行的左侧 ...

  8. java 输入输出头文件_引入的标准头文件与标准输出以及FOR循环

    感觉C学了一遍又一遍,大学学过,工作的时候也学过,奈何一直在弄JAVA,没有怎么用过C,学了就忘,忘了就....算了-- 现在搞音视频开发,又必须弄到这一块了.因此,写点东西回加强记忆.是的,基础本来 ...

  9. bool类型头文件_[C++基础入门] 2、数据类型

    点击上方 蓝字 关注我呀! [C++基础入门] 2.数据类型 文章目录 2 数据类型 2.1 整型 2.2 sizeof关键字 2.3 实型(浮点型) 2.4 字符型 2.5 转义字符 2.6 字符串 ...

最新文章

  1. Segmentation fault到底是何方妖孽
  2. 一篇文章教你弄懂java CMS垃圾回收日志
  3. Item9:总是要改写toString
  4. Flask 应用的文件结构
  5. 高颜值可定制在线绘图工具
  6. 关于python中字典描述正确的是_python总结七
  7. 服务器linux什么镜像好用,Linux系统镜像建站Debian和Ubuntu选择哪个比较好
  8. GreenSock GSAP 3.0 最新版 所有内容创建于2020年4月4日
  9. 记录一下postman汉化踩过的坑
  10. 数学物理计算机的思考
  11. spring cloud day(6) gateway网关
  12. Unity 之 2D水插件推荐和模拟水效果制作分享
  13. 日记20050930
  14. Windows 10 显示桌面图标 计算机 / 此电脑 / 我的电脑
  15. 腾讯游戏助手运行闪退日志查看
  16. 实战分享:一文读懂RS-232总线
  17. 微型四轴DIY机架,轻巧稳固耐摔,通用720空心杯电机,9厘米轴距
  18. 数学家的情书-笛卡尔的心型线方程
  19. onReachBottom无法触发也不报错
  20. matlab生成一个数值一样的向量

热门文章

  1. 印度:银行区块链联盟计划改善小企业融资
  2. 艺术|油画|欣赏| 遥想当年赤壁
  3. 最新没写博客,晒晒家里的技术书吧
  4. 如何让Termux上的Nethunter访问手机内存(无root)
  5. 获取页面链接后携带的参数
  6. 6.3 排列活动顺序
  7. 扫地机器人就是个鸡肋
  8. 4.Altiris cms 7.0 首次设置
  9. web端测试和移动端测试的区别
  10. 真实时在线K歌,全音乐版权支持|网易云信一体化实时合唱解决方案有一套!...