解析c语言中的sizeof(精选6篇)
一、sizeof的概念
sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。
二、sizeof的使用方法
1、用于数据类型
sizeof使用形式:sizeof(type)
数据类型必须用括号括住。如sizeof(int)。
2、用于变量
sizeof使用形式:sizeof(var_name)或sizeof var_name
变量名可以不用括号括住。如sizeof (var_name),sizeof var_name等都是正确形式。带括号的用法更普遍,大多数程序员采用这种形式。
注意:sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。
如sizeof(max)若此时变量max定义为int max,sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式。
三、sizeof的结果
sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。
1、若操作数具有类型char、unsigned char或signed char,其结果等于1。
ANSI C正式规定字符类型为1字节。
2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、float、double、long double类型的sizeof 在ANSI C中没有具体规定,大小依赖于实现,一般可能分别为2、2、2、2、4、4、4、8、10,
3、当操作数是指针时,sizeof依赖于编译器。例如Microsoft C/C++7.0中,near类指针字节数为2,far、huge类指针字节数为4。一般Unix的指针字节数为4。
4、当操作数具有数组类型时,其结果是数组的总字节数。
5、联合类型操作数的sizeof是其最大字节成员的字节数。结构类型操作数的sizeof是这种类型对象的总字节数,包括任何垫补在内。
让我们看如下结构:
struct a;
在某些机器上sizeof(a)=12,而一般sizeof(char)+ sizeof(double)=9。
这是因为编译器在考虑对齐问题时,在结构中插入空位以控制各成员对象的地址对齐。如double类型的结构成员x要放在被4整除的地址。
6、如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。
四、sizeof与其他操作符的关系
sizeof的优先级为2级,比/、%等3级运算符优先级高。它可以与其他操作符一起组成表达式。如i*sizeof(int);其中i为int类型变量。
五、sizeof的主要用途
1、sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如:
void *malloc(size_t size),
size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。
2、sizeof的另一个的主要用途是计算数组中元素的个数。例如:
void * memset(void * s,int c,sizeof(s))。
六、建议
由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用ziseof来代替常量计算。
原文转自:www.ltesting.net
C语言作为一种计算机高级语言, 既适合编写系统程序又适合编写应用程序, 同时具有汇编语言和高级语言的双重特性, 具有强大的功能, 是当今最受欢迎的计算机语言之一, 已成为大中专院校计算机专业和非计算机专业的必修课程。但是由于C语言的语法多、数据类型结构丰富、表示式类型多样化、程序设计自由度大、源程序书写格式自由等诸多问题, 学习、熟练、掌握、灵活运用C语言并不容易。其中最关键的问题是运算符的使用。本文将对C语言的运算符从定义、使用到注意事项逐一解析。
C语言的运算范围很宽, 具有非常丰富的运算符, 如:自增 (++) 、自减 (--) 、位运算符等, 共有34种运算符。运算符是告诉编译器对运算对象进行某种操作运算的符号。C语言常用的运算符有三类:算术运算符、关系与逻辑运算符、位运算符。除此之外, 还有一些用于完成特种任务的特种运算符, 如:强制类型转换运算符 ( () ) 、条件运算符 (?:) 、赋值运算符、逗号运算符 (, ) 和自增 (++) 、自减 (--) 运算符等。各种运算符的优先级如图1所示。
1 算术运算符和算术表达式
C语言中, 算术运算符用于各类数值运算。基本的算术运算符有+、-、*、/及求余%5种, 其运算规则与代数运算基本相同, 需要说明的是, / (除) 运算中, 其商为整数, 小数部分被舍弃, 例如:5/2=2, 若两个运算对象中至少有一个是实型, 则运算结果为实型, 例如5.0/2=2.5, % (求余) 运算, 要求运算符两侧的操作数均为整型数据才有意义, 否则出错, 结果是整除后的余数。
1.1 算术运算符的优先级运算规则
按先乘除后加减的运算符的优先级次序执行。算术运算符遵循自左向右的左结合性运算规则, 即运算对象先与左边的运算符结合。
1.2 强制类型转换运算符
可以利用强制类型转换运算符“ () ”将一个表达式转换成所需要的类型。一般格式为: (类型名) (表达式) 。在进行强制类型转换时, 类型关键字 (或表达式) 名必须用圆括号括起来, 例如: (int) x不能写成int x, (float) (a+b) 不能写成 (float) a+b。
注意两点:①在强制类型转换时, 原来变量的类型未发生变化;②算术表达式中若含有不同类型数量值的混合运算, 遵循优先级和结合性外, 遵循低精度类型转换为高精度类型自动类型转换规则。如4+3.5结果为7.5。
1.3 自增 (++) 、自减 (--) 运算符
在C语言中有两个很有用的运算符, 就是自增1和自减1运算符“++”和“--”, 运算符“++”是操作数自加1, 而 “--”则是操作数自减1, 即++x等同于x=x+1, --x等同于x=x-1。注意:该运算符只用于变量, 不可用于常量和表达式。
还需特别强调的是, “++”和“--”运算符放在操作数之前和之后的运算的意义不同。例如:i++表示在使用了i之后再使其值加1, ++i则表示在使用i之前先使其值加1, 举例来说, 如x=2;y=++x;此时y=3;若将程序改为x=2;y=x++;则y=2;在这两种情况下, x的值都被置为3, 其区别在于运算的过程控制。
自增自减运算符这种在运算过程中的控制是很有用的, 生成代码块, 目前在C语言中被广泛使用, 已成为C语言的主要风格之一, 选用运算符“++”和“--”来完成增1和减1的运算功能是目前一个很好的选择。
2 关系运算符和关系表达式
关系运算符用于比较运算, 是对两个表达式进行比较, 返回一个真/假值, C语言中关系运算符有6个, 如表1所示。
用关系运算符将C语言的两个表达式 (可以是算术表达式、关系表达式、逻辑表达式、赋值表达式等) 连接起来的式子称为关系表达式, 其形式为:表达式1关系表达式表达式2, 如a+b>c+d, 若表达式成立, 其结果是“逻辑真”用“1”表示, 若表达式不成立, 其结果是“逻辑假”用“0”表示, 关系表达式的结果只能且必为二者之一。
3 逻辑运算符和逻辑表达式
逻辑运算符用于逻辑运算, 即对问题进行逻辑判断, C语言提供三种逻辑运算符, 包括&&逻辑与 (相当于同时And) 、‖逻辑或 (相当于或者Or) 、!逻辑非 (相当于否定Not) 。
用逻辑运算符将1个或多个表达式连接起来进行逻辑运算的式子称为逻辑表达式。逻辑运算结果为一个整数值0或1, 0代表“假”, 非零代表“真”。例如:x=5, 则 (x>=0) && (x<=10) 的值为“真”, (x<=-1) ‖ (x>5) 的值为“假”。其运算规则如表2所示。
注意:在进行逻辑“&&”运算时, 若第一个表达式的值为假, 则第二个表达式不再需要计算, 第二个表达式不参与计算, 且值保持不变, 只有第一个表达式是值为真时, 才要计算第二个表达式的值。同理, 对于“‖”运算, 只要第一个表达式的值为真, 则第二个表达式不再计算, 若第一个表达式的值为假, 才要计算第二个表达式的值。
4 赋值运算符和赋值表达式
C语言的赋值运算符分为简单赋值 (=) 和复合赋值 (+=、-=、*=、/=、%=、&=、︱=、∧=、<<=、>>=) 共11种。
简单赋值表达式的一般形式为:变量=表达式。系统先计算=右边表达式的值, 再将其结果的数据类型转换为左边变量的数据类型, 最后将转换结果赋值给左边变量, 赋值表达式的值是左边变量所得到的值。注意:“=”不同于“==”, “=”表示赋值运算符, “==”表示等号运算符, 它们是两种完全不同的运算符。在有些判断语句中, 用“=”表示比较运算而不是用“==”, 如if (x=4) printf (“yes”) ;else printf (“no”) 。
复合赋值表达式的一般格式为:变量复合赋值运算符表达式, 等价于变量=变量双目运算符表达式。如x+=3等价于x=x+3;y*=x+6等价于y=y* (x+6) 。注意:被赋值的变量必须是单个变量, 且必须在赋值运算符的左边。且赋值是指将赋值运算符右侧的数据存入赋值运算符左侧变量所表示的内存单元中。如x=5表示将常量表达式5放入由变量x表示的存储单元, 即将5赋予x。
C语言允许将赋值运算作为表达式, 且允许出现在其他语句 (如循环语句) 中。复合赋值运算符和赋值表达式及运算规则如表3所示。
5 条件运算符和条件表达式
条件运算符是C语言中唯一一个三目运算符, 用于条件求值。一般格式为:表达式1 表达式2:表达式3, 其含义是, 若表达式1的值为非0, 条件表达式取表达式2的值;若表达式1的值为0, 条件表达式取表达式3的值作为最后的结果。如:7>3 1:-1, 7>3关系运算的结果为1, 故该条件表达式的值为1。
6 逗号运算符和逗号表达式
恰当地使用逗号表达式可以简化程序设计。逗号表达式常用在for语句中, 一般形式为表达式1, 表达式2, ……, 表达式n, 从左至右依次计算表达式的值, 最后“表达式n”的值即为整个逗号表达式的值。例如, 逗号表达式“a=3*5, a*4”的值为60:先求解a=3*5, 得a=15;再求a*4=60, 所以逗号表达式的值为60。
用一个逗号表达式语句可代替多个赋值语句, 如:a=0, b=1, c=2;在语法上作为一条语句, 它相当于下面3条语句:a=0;b=1;c=2;用一个逗号表达式语句可得到多个计算结果, 如:y=10, x= (y=y-5, 60/y) ;执行后, 可同时得到x的值为12, y的值为5.需要注意的是, 逗号运算符不同于逗号分隔符, 如int a=5;printf (“%d, %d, %d”, a, ++a, ++a) ;语句中逗号是分隔符, 分割printf函数的三个参数, printf函数运算规则是从右到左, 最后输出的结果是7, 7, 6, 而不是5, 6, 7。
7 位运算符
C语言为整型数据提供了位运算符, 以字节中的每个二进制位为运算对象, 最终的运算结果还是整型数据。位运算又分为按位逻辑运算和移位运算。
7.1 位逻辑运算
按位逻辑运算符有4种, 如表4所示。参与运算时, 操作数都必须首先转换成二进制数, 然后再执行相应的按位运算。位逻辑运算符的优先级从高到低依次为:按位取反运算符、&运算符、︱运算符、∧运算符。
7.2 位移运算
左移或右移时出现的空位应当补0, 运算规则如表5所示。
8 结束语
C语言中运算符和表达式数量之多, 使得C语言的功能十分完善, 如何正确有效地使用和掌握C语言的运算符和表达式让是许多学习者感到困惑的问题。本文从这些问题出发, 对C语言的运算符和表达式进行了系统的解析, 对容易出现问题的地方进行了强调, 提出了相应的解决方法, 希望对C语言的学习者有所帮助。
参考文献
[1]李铮.C语言程序设计基础与应用[M].北京:清华大学出版社, 2005.
[2]何光明.C语言程序设计[M].北京:清华大学出版社, 2007.
[3]刘新铭.C语言程序设计教程[M].北京:机械工业出版社, 2006.
[4]高福成.C语言程序设计教程[M].北京:清华大学出版社, 2004.
[5]伍一.C语言程序设计基础与实训教程[M].北京:清华大学出版社, 2005.
函数是C语言中的重要概念。利用好函数能够充分利用系统库的功能写出模块独立、易于维护和修改的程序。
函数并不是C语言独有的概念,其他语言中的方法、过程等本质上都是函数。可见函数在教学中的重要意义。
在教学中一般采用画简单的堆栈图的方式描述函数调用,但由于学生对堆栈没有直观认识,难以深入理解,因此教学效果往往并不理想,从而限制了对模块化程序设计思想的理解和应用。
2 解决方法
在《微机原理》课程介绍了堆栈、汇编语言等必要的相关知识之后,通过在高级语言开发环境下反汇编C语言程序代码,使得学生通过分析汇编代码来理解函数调用中的堆栈变化,可以在实践中理解高级语言和低级语言的底层映射关系,理解函数调用的实质。
本文通过在Visual C++6.0下反汇编一个32位C语言程序的部分代码来解析解释函数调用的具体过程。
3 函数调用过程
函数调用过程主要由参数传递、地址跳转、局部变量分配和赋初值、执行函数体,结果返回等几个步骤组成[1]。
3.1 参数传递及函数跳转
参数由实参传递给形参。在底层实现上,即是实参按照函数调用规定压入堆栈。参数传递完成后就通过CALL指令由当前程序跳转到子程序处。
3.2 局部变量分配并赋值
函数的“{”被认为是分配局部变量空间的时机。在汇编层面局部变量分配体现为堆栈中以EBP寄存器为基址向低地址端分配的一个连续区域,通过EBP寄存器的相对寻址方式来寻址函数内的局部变量。
由于堆栈增长的方向是高地址端到低地址端,因此函数中先定义的局部变量地址较大,后定义的变量地址逐渐变小,相邻定义的变量其地址一定相邻[2]。由于全局数据和局部数据定义在不用的数据区而并不与局部变量相邻,根据程序局部性原理,相邻的数据会被缓存,因此对相同的运算,局部变量作为操作数的运算效率就可能高于有全局变量参与的运算。同时,局部变量分配和回收只需要移动堆栈指针ESP,因此效率最高。
3.3 寻址函数的参数
参数存放在以EBP为基址的高地址端。对参数的访问同样是通过EBP寄存器相对寻址操作来实现。
3.4 执行函数体内的语句
函数内和具体功能相关的语句被转化成一系列汇编语句。
3.5 返回值
return语句将返回值返回到主调函数。在底层,参数是通过EAX寄存器或EDX寄存器传递给主调函数。
3.6 返回主调函数
函数的“}”被解释为函数体已经执行完。遇到“}”时,会将堆栈中的局部变量、程序中压入堆栈的寄存器的值全部弹出,将之前CALL指令执行时压入堆栈的函数返回地址弹到指令指针寄存器EIP,从而返回到主调函数。
3.7 堆栈平衡
堆栈平衡指的是将函数调用前压入堆栈的参数弹出堆栈,使堆栈恢复到其调用前的状态[3]。由于函数调用完成后,参数就是无用的数据了,因此需要将其移出堆栈。
在C语言中不需要进行堆栈平衡。而在汇编层面上却根据调用约定来确定由主调函数或是被调函数完成堆栈平衡。
C语言函数调用堆栈常见形式如图1所示[4]:
参数由主调函数压入堆栈,CALL指令将函数返回地址入栈。进入子函数后,需要保存EBP原值、分配局部变量空间、保存寄存器初始值。函数内通过“EBP-位移量”方式访问局部变量,通过“EBP+位移量”方式访问参数[5]。
每发生一次函数调用,就会在堆栈中建立一个栈帧,栈帧在函数调用后释放。但是系统的堆栈资源有限,因此如果函数调用(如递归调用)层数过多,则可能发生堆栈溢出错误。
4 反汇编代码分析
以下将函数function的调用相关代码在Visual C++6.0 Debug模式反汇编,通过对汇编代码的分析揭示函数调用的关键点和细节。完整的C语言程序代码如图2所示:
Function(i,&j)语句的反汇编代码如图3所示:
先找到主函数中的局部变量i,j(其在堆栈中位置为EBP-8和EBP-4),将其压入堆栈。Visual C/C++的编译器对C语言程序的默认函数约定为_cdecl[6]。此参数入栈约定为自右向左,并且对函数名前加“_”修饰符。先将j的地址压入堆栈,后将i的值压入堆栈。通过call指令调用函数。从Call指令可见fuction函数编译后加了“_”修饰符。Call指令执行时自动将函数的返回地址入栈,之后转到function定义处开始执行此函数。
对funciton函数的“{”的反汇编结果如图4所示:
在函数内,遇到“{”时分配局部空间。在Debug模式下,这个区域大小为“40H字节+局部变量总字节数”,并用值“0xCCH”进行初始化。未在定义时初始化的局部变量其初值就与“0xCCH”相关。因此int类型变量由于占四个字节,其初值为-858993460(0xCCCCC-CCCH);两个连续的0xCCH对应汉字“烫”字,因此当以字符形式显示函数内未初始化的变量时会显示为“烫烫…”;指针类型变量就指向了地址为0xCCCC-CCH的内存。由此在调试模式下能很容易发现未初始化的变量。
堆栈基本的存储单位为四字节,对于小于四字节的数据按四字节对齐方式分配空间。因此char类型变量ch虽然数据本身需要两个字节,也分配了四个字节空间。array字节数组分配空间时每个字符占一个字节,不够四个字符时按四字节对齐存放。因此局部变量空间总数为40H+4+4×2+4=50H。局部变量ch的地址为EBP-4,a、b的地址分别为EBP-8,EBP-0CH,array数组的地址为EBP-10h。
函数左括号右括号间的所有的语句反汇编结果如图5所示:
若变量有初值,则反汇编就会为其生成一条Mov指令为其赋值。对于没有初值的变量其每个字节都为0x CCH。对于字符数组,情况稍微复杂一些。字符串常量“abc”被存放在全局数据区中。当需要引用其值对数组进行初始化时,实际是将全局数据拷贝到堆栈中的局部数组array里。由于寄存器是32位,每次最多只能赋值4个字符,因此对数组赋初值的语句反汇编后可能产生一至多条汇编语句。
对数组内容的访通过[“EBP+数组首地址+偏移量]的寄存器间址来完成,因此局部数组初始化费时但访问时的效率高。
在函数内访问局部变量和参数通过[EBP+位移量/-位移量]来完成。
函数返回值被放到EAX寄存器中供主调函数使用。
可见,在汇编层面上,函数内部并不存储局部变量,局部变量只有当函数调用发生时才会在栈上为函数分配空间。因此当函数调用后返回局部变量的值是错误的。
遇到函数“{”时的操作如图6所示:
将寄存器EDI、ESI、EBX恢复原值;将ESP调回到EBP处;将EBP原值弹出。此时ESP指向函数返回地址。执行出栈指令,将函数的返回地址弹入EIP寄存器返回到主调函数。
此时堆栈中只残留有调用函数时压入的参数还没有清理。
主调函数中的堆栈平衡语句如图7所示:
根据_cdecl约定,需要由主调函数完成堆栈平衡。主调函数根据压入堆栈的参数的数目2和参数大小,利用指令add ESP,8将参数全部弹出。此时堆栈就恢复到其调用前的状态。一个完整的函数调用过程完成。
5 教学效果
通过对比和实践使学生深刻理解了所学概念,提高了学习兴趣,在实践中找到高级语言中部分约定的底层根源,从而在程序书写中自觉避免相关错误的发生,提升了综合素质。
6 结束语
通过在VC6.0环境下对一个C语言程序反汇编代码、堆栈变化过程的详细分析,揭示了函数调用过程中的几个关键点。对深入了解函数调用、变量分配机制和调试排错起到一定程度的帮助作用。
参考文献
[1]苏小红,陈惠鹏,孙志岗,等.C语言大学实用教程[M].电子工业出版社,2004.
[2]周荷琴,吴秀清.微型计算机原理与接口技术[M].2010.
[3]俞甲子,石凡,潘爱民.程序员的自我修养-链接装载与库[M].电子工业出版社,2009.
[4]李肖坚,钟达夫,夏冰,等.缓冲区溢出原理及植入代码的分析研究[J].计算机应用研究,2007(1):163-166.
[5]李毅超,刘丹,韩宏,等.缓冲区溢出漏洞研究与进展[J].计算机科学,2008(1):87-90.
1 C语言字符数据的基本概念
1.1 字符常量和字符变量
C语言有丰富的数据类型, 包括基本类型、构造类型、指针类型和空类型, 其中基本类型中包含有字符型数据。字符型数据分常量和变量, 字符常量是由单引号’’括起来的ASCII字符, 如’a’。字符变量必须先定义后使用, 如char c1;即定义了一个字符变量c1。字符型变量可以用来存放字符常量, 且它只能存放一个字符, 如c1=’a’;。
1.2 字符串常量
C语言中, 字符串常量是由一对双引号””引起来的字符序列, 如”Intel”、“The C Program Language”。C语言中字符串一一位数组的形式存放在内存中, 因此’A’和“A”所表达的意义不同, ‘A’是单字符常量, 在内存中只占1个字节, 存放字符A的ASCII码, “A”是字符串常量, 在内存中共占2个字节, 其中一个字节存放A字符的ASCII码, 另一个字节自动存放字符串结束标记“�”。
1.3 字符数组
C语言中只有字符串常量而没有字符串变量, 字符串的存取操作必需借助字符数组来实现, 而不能以变量的形式直接进行存取, 存放一个字符串需要先定义一个字符型数组, 而后将字符串中的字符逐个作为字符数组的数组元素进行操作。字符数组中一个元素只能存放一个字符, 如char a:表示定义了一个一维字符数组a, 可存放5个字符, 或存放最大长度为4的1个字符串 (最后一个字符是字符串结束符‘�’) 。字符数组元素的引用通常采用循环结构实现对数组元素的逐个操作。字符数组的初始化分为逐个字符给数组元素赋值和用字符串常量给字符数组初始化两种形式, 由于逐个字符给数组元素赋值操作繁琐, 实际编程中常用字符串常量给字符数组初始化。
2 字符数据的输入与输出
C语言提供了字符数据的输入与输出除了C语言提供的常用scanf () 函数和printf () 函数进行输入与输出操作, 还提供了专用的字符输入函数getchar () 和字符输出函数putchar () 以及字符串输入函数gets () 和字符串输出函数puts () 。
2.1 字符数据的输入
2.1.1 scanf函数
scanf函数的作用是输入若干个任意类型的数据, 是一种格式输入函数, 利用scanf函数给字符变量赋值应使用格式说明“%c”即可实现字符输入。用scanf函数输入其他类型的数据时, 数据间可以用空格来分隔, 而用回车表示输入结束, 但用“%c”格式输入字符时, 空格和“转义字符”都会作为有效字符输入, 因此使用时容易出错。例如:scanf“ (%c%c%c”, &c1, &c2, &c3) ;若要将字符’a’、’b’、’c’分别赋给变量c1、c2、c3, 正确的输入方法是“abc”, 如果输入“a空格b空格c”, 则c1=’a’, c2=’空格’, c3=’b’, 将产生错误。在连续使用两个及以上scanf函数输入字符数据时最容易出现问题, 有下列程序:
printf ("输入两个整数:") ;scanf ("%d%d", &a, &b) ;
printf ("输入两个字符:") ;scanf ("%c%c", &c1, &c2) ;
运行程序输入“5空格8 HE”, 结果是:a=5, b=8, c1=’n’, c2=’H’, 将产生错误, 出现这种情况的原因是输入的第一个回车表示输入结束, 但该回车被下一个scanf函数的第一个变量c1接收而成为换行符’n’, 而字符’H’赋给了变量c2, 输入的字符’E’未被任何变量接收。解决此问题的办法是在第二个scanf函数的格式控制部分第一个“%c”前加一个空格, 这样在输入时第一个回车就不会被变量c1接收了, 问题得到解决。
2.1.2 getchar函数
getchar函数的作用是从终端 (通常是键盘) 输入一个字符, 其函数值就是从键盘输入的字符, 可将函数值赋给字符变量, 如:char c1;c1=getchar () ;程序运行到getchar函数时, 等待用户从键盘输入字符, 在键盘上输入“a”, 则c1=’a’。若是两个变量输入, 程序如下:char c1, c2;c1=getchar () ;c2=getchar () ;想得到c 1=’a’, c 2=’b’, 程序运行后输入‘a‘后输入就会结束, 第二个字符’b‘无法输入, 而此时c1=’a’, c2=’n’。正确的输入方法是在键盘上输入“ab”, 此时c1=’a’, c2=’b’。由此可以得出, 在使用getchar进行字符输入时, 按回车键表示输入结束, 但同时按回车键也产生一个转义字符’n’, 这个字符会被后面的getchar函数接收, 因此利用连续多个getchar () 函数给多个字符变量赋值时应注意只在最后一个字符后面按回车键, 其它字符连续输入, 字符间不要添加任何符号, 否则会产生错误。
2.1.3 gets () 函数
gets () 函数的作用是从终端输入一个字符串到字符数组中。如:char str1[13];gets (str) ;从键盘输入“How are you?”, 则数组str1的值为字符串“How are you?”。输入时以回车表示输入结束, 这与scanf函数一致, 但需要注意的是利用gets函数输入字符串时, 输入结束时所按的回车键会被转化为字符串结束标志’�’, 而利用scanf函数输入字符串时回车不会被转化为’�’。
2.2 字符数据的输出
2.2.1 printf () 函数
printf () 函数的作用是输出若干个任意类型的数据, 对不同类型的数据用不同的格式字符。d格式符以十进制整数形式输出、x格式符以十六进制数形式输出整数、c格式符以单个字符形式输出、s格式符以字符串形式输出、f格式符以小数形式输出实数。printf () 函数输出时还可以在符号前面以m.n的形式控制数据显示的列数和精度。
2.2.2 putchar () 函数
putchar () 函数的作用是向终端输出一个字符, 字符内容可以是单字符常量、字符变量、ASCII码和转义字符。如:putchar (‘h’) 、putchar (c1) 、putchar (65) 、putchar (‘n’) 将分别输出单字符h、字符变量c1、字符A和换行符。
2.2.3 puts () 函数
p u t s函数的作用是将一个字符串 (以’�’结束的字符序列) 输出到终端, 在输出时将字符串结束标志’�’转换成’n’, 即输出完字符串后换行, 而用printf函数的“%s”格式输出字符串时不会将字符串结束标志’�’转换成’n’, 如果需要换行必须书写语句printf (“n”) 来实现。
3 结束语
在C语言程序设计中数据的输入与输出是最为常用的操作, 而字符数据因其自身的特点在输入输出方面又具有一定的特殊性, 一般情况下, scanf () 和printf () 、getchar () 和putchar () 、gets () 和puts () 配对使用, 在学习过程中必须多实践, 多练习, 在实际编程过程中掌握有关字符数据输入与输出的方法, 进而提高编程能力, 掌握C语言程序设计的技巧。
摘要:随着单片机技术的飞速发展C语言逐步成为单片机编程的重要语言, C语言程序设计课程不仅是高校计算机专业必修课, 也成为电子相关专业的一门重要的专业基础课程, 在学习过程中C语言字符数据的输入与输出是教学的难点与重点之一, 也是学生容易出错的知识点。通过教学实例重点分析C语言字符数据输入与输出易出错原因, 提出解决办法, 使教学更具针对性, 有效提高课堂教学质量。
关键词:单片机,C语言,字符数据,输入,输出
参考文献
[1]谭浩强.C程序设计试题汇编[M].北京:清华大学出版社, 1998.
[2]葛素娟, 胡建宏.C语言程序设计教程[M].北京:机械工业出版社, 2013:41-47.
关键词:C语言,专业基础课,激发,兴趣
一、名片制作
在屏幕上输出个人信息(姓名、寝室号、QQ、手机号)。
1. 实训过程
A、打开Win_TC编辑器,编写代码
B、保存并运行(Ctrl+F9)
2. 所用到的知识点有:
A、文本窗口颜色的设置,头文件#include"conio.h",设置文本窗口的颜色textcolor(YELLOW);textbackground(GREEN);清除屏幕内容从而添加文本颜色。
B、光标定位函数gotoxy(20,8);C、输出函数printf();
3. 案例扩展
A、简化代码(考虑用循环输出外边框,以及打印星号)
B、以上是固定的死名片,请制作一动态名片(字符串的输入输出)
C、在名片中加入性别和年龄两项内容,并控制好输出。(数据类型的定义)
注:用定位函数输也各种图形(直角三角形、平行四边形、六边形,五角星等)
二、TAXI计费器
制作一个Taxi计费器,重点是模拟Taxi的计费方式:2公里内起步价,2公里之外的是,起步价加每公里单价。此时我们必须对公里数进行判断并计算总价。
1. 实训过程
A、定义符号常量,定义变量;B、输入路程多少公里;C、根据不同的公里数计算出相应的总费用;D、输出计算出的总费用;E、用简单的for循环方便测试两次看不同的结果。
2. 所用到的知识点有:
A、符号常量的定义;B、变量的定义、赋值;C、输入函数的使用;D、运算符和表达式;E、分支语句;F、输出函数的使用
3. 案例扩展
实现神州专车的估价程序。
注:本阶段完成圆的计算器,班费管理器
三、字母转换器
制作一个字母转换器,将所输入的大写字母转换为小写字母,小写字母转换为大写字母,若输入的不是字母的字符能提示输入的不是字母。
1. 实训过程
A、定义一个输入的字符和一个转换后的字母。char chbegin,chend;B、输入一个字符。chbegin=getchar();C、用条件分支判断进行转换。if,else;D、输出转换后的结果。printf();E、用简单的for循环方便测试三次看不同的结果。
2. 所用到的知识点有:
A、变量的定义;B、字符输入函数的使用;C、运算符和表达式;D、分支语句;E、输出函数的使用
3. 案例扩展
输入有误时能提示重新输入。
四、登陆系统
制作一个用户登录系统,可以注册登录,输错密码要能进行退格修改,在登录时,错误要能提示!细化到帐号还是密码错误。
1. 实训过程
A、说明部分:定义id[20],password[20],userid[20],userpassword[20],temp;B、对注册部分进行编写,以及输入密码的代码:字符转换成*号:用中间变量temp接受并判断若不为退格键则password[i++]=temp,当用户按下退格要能实现退格printf("bb");并将密码位置前移,i--;C、登录:输入注册好的账号和密码,用strcmp进行比较登录;D、登录成功,清屏printf("welcome");失败则重新登录
2. 所用到的知识点有:
A、字符数组的定义,存储;B、分支语句;C、循环语句
3. 案例扩展
A、当用户按下“空格键”、“ESC”时,也能实现相应的功能;B、错误信息提示能用窗口信息突显出来。
五、作业抽查器
当我们在上课的过程中,老师时常要点名检查同学们的作业,如果经常检查某些同学的,其它同学会认为不公平,为公平起见,我们可以利用程序随机生成多个互不相同的学号,为了便于老师点名查看所产生的学号,需对所产生的多个学号进行排序。
1. 实训过程
A、说明部分,由于需要产生多个学号,因此定义一个整型数组;B、、产生多个互不相同的随机数并依次赋值给数组。先任意产生一个数赋值给数组中的第一个数,之后每产生一个数都要和它之前的所有元素比较,若相同则重新产生一个数。以至产生完所有的数;C、对上面所产生的多个互不相同的数进行排序;D、最后输出排序后的数。
2. 所用到的知识点有:
A、数组的定义;B、rand()方法产生随机数;C、数组的排序;D、遍历输出数元素
3. 案例扩展
日常生活中,每堂课上都可能有学生要请假,而请假了的学生肯定不能被抽查到,否则此作业抽查器就没意义了,因此,要求通过程序保证一定不会抽到请假的学生的学号。
参考文献
[1]陈娟,张军.基于CDIO的电子类专业的C语言教学内容的研究[J].电脑知识与技术.2016(20)
[2]武越.C语言教学现状剖析与改革[J].农业网络信息.2015(03)
[3]陈红.翻转课堂在高职院校非计算机专业C语言教学改革中的应用与实践[J].电脑知识与技术.2016(05)
[4]李丽新.高校非计算机专业C语言教学改革的探讨[J].吉林建筑大学学报.2015(01)
[5]夏利玲.微课在高职C语言教学中的应用研究[J].新校园(上旬).2015(10)
1 资料与方法
1.1 一般资料:
根据观察组105例在2008年1月至2009年1月住院患儿的病史、临床表现、查体及胸部X线检查、血常规、血或痰培养的结果, 做出诊断。病毒性肺炎组26例, 男14例、女12例, 支原体肺炎组35例, 男19例、女16例。细菌性肺炎组44例, 男24例、女20例, 健康对照组30例, 来自同期门诊体检健康的儿童, 男16例、女14例。4组性别、年龄均无明显差异 (P>0.05) , 具有可比性。
1.2 方法:
在肺炎急性期 (临床症状体征明显, 胸片异常) , 对观察组105例肺炎患儿和健康对照组30名儿童进行空腹状态的静脉抽血3 m L, 血清离心分离, 之后用日立7600-020型全自动生化分析仪及西班牙Bio Svstems试剂盒, 并采用免疫比浊法进行CRP水平的检测, 最后对比分析。
1.3 评价指标:
将两组患者的CRP水平作为检测的数据, 进行对比, 得出结论。
1.4 统计学处理:
采用SPSS13.0统计软件。计量资料以均数±标准差表示, 组间均数比较采用独立样本t检验, 多组间均数比较采用方差分析, 计数资料采用率表示, 多组间率比较采用χ2检验, P<0.05具有统计学差异。
2 结果
通过研究记录对比, 细菌性肺炎组, 支原体肺炎组, 病毒性肺炎组和健康肺炎组机组对比, 血清C-反应蛋白最高的是细菌性肺炎组, 达到 (63.0±37.5) mg/L;其他组血清C-反应蛋白由高到低依次是支原体肺炎组, 病毒性肺炎组和健康对照, 数值分别为 (15.2±8.9) mg/L, (2.9±1.8) mg/L, (2.1±1.5) mg/L, 后两组对比无统计学意义 (P>0.05) 。
3 讨论
婴幼儿时期最容易发生肺炎, 这是由于多方面原因造成, 主要还是呼吸系统生理解剖上的特点所致, 婴幼儿的气管, 支气管等呼吸气管都没有发育完全, 可能会产生狭窄, 另外气管内部的黏液, 纤毛都可能会发育不全, 造成数量的减少, 运动的减弱, 或者更为直接的是肺部肺泡的数量不足等, 这都是直接造成小儿易于发病的原因[3]。除此以外, 婴幼儿的其他系统也存在漏洞。像是免疫力都很低下, 本身容易遭受病毒细菌的侵袭, 而一旦遭受侵袭, 由于抗体数量的不足, 肺炎更容易扩散, 造成大面积的炎症。而岁数较大的婴幼儿, 相应的免疫力会有所增加, 也就减少了得病的风险。
C-反应蛋白作为一种能与肺炎链球菌C多糖体反应形成复合物的, 在病原体进入机体的早期大量生成而广泛分布于各组织中的人类急性时相反应蛋白, 是在病原体入侵导致炎症或机体急性组织损伤等刺激时, 由肝脏合成的含量在短时间内迅速升高的急性时相蛋白, 健康人体血液中含量极少, 约为3.5 mg/L。
CRP作为与细菌胞壁的磷酸胆碱及核染色质结合的急性时相蛋白, 激活补体与C1q的结合, 并引起C3b沉着在微生物上, 继而表达C3b受体的吞噬细胞将细菌吞噬。在细胞内增殖的病毒, 磷脂未能暴露在细胞膜上, 因而不能激发CRP的产生和结合。而发生在细胞外的细菌感染, 则分离了两边的细胞膜, 使得磷酸胆碱分子暴露出来并为CRP提供附着点, 再将信息通过IL-6传递给肝脏, 刺激产生CRP。CRP是一种可衡量急性感染的指标, 并具有极高的敏感性, 能将机体的感染情况快速、准确地反映出来, 在疾病发作时可早于WBC上升, 也能很快回复正常。不受性别、年龄、贫血、高球蛋白血症等因素的影响, 不受放疗、化疗、糖皮质激素治疗的影响, 而优于其他急性期的反应物质。CRP的合成在急性炎症的4~6 h内迅速增加, 倍增发生在其后的8 h, 阳性率高达96%。被病毒感染的大多数患儿CRP值降低或轻微升高。而细菌感染时CRP增高, 可达150~350 mg/L。所以, CRP能为炎性反应的早期提供临床依据。研究结果表明, 支原体肺炎患儿血清CRP水平稍高, 细菌性肺炎患儿血清CRP水平明显增高, 而病毒性肺炎患儿几乎接近健康对照组水平。病毒性肺炎与支原体肺炎间比较也有非常显著的差异。引起CRP升高的支原体感染, 其机制可能为细胞膜被支原体直接损伤, 使胆碱磷酸分子和CRP的附着点暴露出来, 再将信息通过白细胞介素6 (IL-6) 等传递给肝脏而产生大量CRP, 因而CRP也可作为支原体所致组织损伤的敏感指标。因此, 血清CRP可作为鉴别病毒性肺炎、支原体肺炎和细菌性肺炎的指标之一。
摘要:目的 研究在小儿肺炎诊断中血清C-反应蛋白 (CRP) 水平的临床意义。方法 实验组为105例小儿肺炎患者, 对照组为30名健康儿童, 使用日立7600-020全自动生化分析方法测定血清CRP水平, 并利用统计学进行数据分析。结果 在比较病毒性肺炎组和健康对照组的血清CRP时, 无显著差异 (P>0.05) 。而支原体肺炎组、细菌性肺炎组却发现有极显著差异 (P<0.01) 。结论 在小儿肺炎辨别诊断中血清CRP水平具有重要临床意义。
关键词:C-反应蛋白,小儿肺炎,临床价值
参考文献
[1]于洁.儿科学[M].北京:人民卫生出版社, 2009:283.
[2]陈全景, 查志刚, 雷勋明, 等.超敏C反应蛋白在小儿支原体肺炎急性期和恢复期的水平变化[J].微循环学杂志, 2009, 19 (3) :71-72.
【解析c语言中的sizeof】推荐阅读:
梦境语言和梦的解析01-11
论语中的成语解析02-07
芭蕾舞剧中的中国特色解析12-03
音乐剧猫中的音乐解析01-28
解析法在几何中的应用02-08
难点解析05-29
路考步骤解析06-17
名句名篇解析06-28
材料解析题07-11
迪拜建筑解析09-11