C学习笔记(一)

1、C程序执行过程:编辑(源程序.c)->编译(目标文件.obj)->连接库函数(可执行目标程序.exe)->运行目标程序

2、C的常量:C中常量用宏定义【#define 常量名 常量值】的方式来定义,这种长常量称为符号常量,而如1、-1.2为直接常量。关键字const用来修饰“只读变量”,与常量有本质区别。

3、C基本数据类型长度:不同的编译器对同一种基本数据类型如int分配不同长度的空间。Turbo分配2个字节,GCC、VisualC++6.0和Visual Studio分配4个字节。(ANSI标准是2字节)。

       整型数据分为short、int、long,还根据有无符号为分为signed和unsigned,故总共6种。

       signed用于存放有符号位的整型。由于用补码存储,最高位为1表示负数,0表示正数。无符号整型只用于存放正数,同一长度的整型,unsigned与signed可表示的正数多一倍,总共可表示的数字个数相同。以2字节的unsignedint和signedint为例分别表示0-65535和-32768-32767。

     在C中,short、int、long之间没有绝对的长度关系(并不一定short2字节int4字节long8字节),但满足short<=int<=long,所以有可能int与long的长度相同。具体以编译系统而定(早期int是2字节,所有有4字节的long来表示更大的数,但现在int已普遍4字节,与4字节的long表示范围相同。在64位操作系统上int是4字节,long是8字节)。可用sizeof(int)查看当前编译环境下的长度。(sizeof是一个求字节数的运算符,而非函数

       同理对于常量,12345u表示无符号int常量;-12345u表示其对应的补码(53191)表示的正整数。

4、关于溢出:对于4个字节的int型,inta=2147483647;a+1的结果是溢出成-2147483648;而若short为2个字节,shortb=32767;b+1得到32768。因为b+1执行过程中将b转化为int所以不会溢出。

limits.h头文件中有int最小值和最大值INT_MIN和INT_MAX。

5、变量声明位置:在标准C中,要求局部变量定义必须在函数或局部空间的开头,然后才能有其他语句!如在main()中声明inta必须在main的开头,然后使用a。若在inta之前有其他printf语句,再inta则出现错误。

       除非将变量声明在分程序中——用{}包裹。如…其他语句…{intc=a+1;}…其他语句…

C++/Java对变量声明的位置没有要求。

6、C中浮点型分为float(单精度)、double(双精度)、longdouble(长双精度),通常分别为4字节、8字节、16字节。浮点型数据采用指数形式存储,分为符号位+小数部分+指数部分。不同的浮点数据类型最大的差别除了可表示的范围还在有效数位数(化成“.xxxxxxx”的形式,小数点后有几位即有效数)。float有效数7位。故同一个数字用不同类型表示其可以表示的有效数不同,精度不同。编译系统默认将float当作double参与运算,可在数值后加“f”让系统按单精度float处理。如floata=111111.111;float型只能接收7位,后两位失效。而double型(有效16位)则能完全表示。(同整型一样,浮点型也因编译系统不同而有差异)

+

.1111111

6

符号位

小数部分(以有效数为准)

指数

其准确表示的数值为.1111111*10^6=111111.1。但float有24bit用于存放小数部分(包括符号位),故有效数后的数字就不准确了。

7、赋值初始化:C中变量可以在声明后连续赋值。如inta,b,c;a=b=c=1;在声明时不能连续赋值。初始化不是在编译时完成的,而是在执行本函数时赋值的只有静态存储变量和外部变量的初始化在编译时完成

       【<变量><赋值运算符><表达式>】赋值表达式按照“从右至左”的顺序结合。a=(b=5)+(c=6);等到b=5,c=6,a=11。赋值表达式可以作为左值,如(a=3*5)=3*4;先将3*5赋给a,再将3*4赋给a。而(a=3*5)=3*4则不行,因为3*5是常量不能作为左值。

8、对表达式做自增或自减运算是不合法的。如(a+b)++、(-i)++是不合法的,因为运算的结果不知道存放在哪里。(-i)是一个减法运算,而j=-i++是合法的——将-i赋给j,i再加1。

       不同系统对有歧义的表达式解释不同,其结果也会不同。如i=3;printf(“%d,%d”,I,i++);有的系统对函数的实参从左至右求值,输出3,3。而有的系统则从右至左求值,输出4,3。编程时要根据系统特性谨慎对待++、--。

9、逗号表达式【表达式1,表达式2,…表达式n】整个逗号表达式的结果是表达式n的结果。如(a=3*5,a*4),a+5;如果这个作为一个执行语句,a的结果是15,整个表达式的结果是20,虽然有a*4但没有赋值给a,也不作为最终结果。逗号表达式是想把多个表达式串联起来运算,并不一定要获得最后一个表达式的值。若要将最后的结果取出仍要赋值语句:a=((a=3*5,a*4),a+5);a最终为20。注意:a=(a=3*5,a*4),a+5;a的结果是60。因为“a=(a=3*5,a*4),”整个是一个赋值表达式。

10、输入输出:输入输出函数并不是C语言本身的语句,而是由编译系统的函数库提供的。将输入输出语句与C源程序分开是为了使编译系统简化,提高可移植性。因为不同的编译系统提供的函数库的函数的名称、参数不尽相同。将源程序编译成目标程序后,再与函数库连接生产可执行文件。编译系统的函数库中是计算机厂商根据用户需求编写的,并且已经生产目标文件,并不会对其编译。故一个C程序中有printf函数时,编译时并不会翻译成目标指令,在连接阶段与系统函数库相连接后,在执行阶段中调用函数库的中printf函数。

       尽管不同编译系统提供不同的函数库,但有一批“标准输入输出函数”,即stdio.h提供的putchar(输出字符)、getchar(输入字符)、printf(格式输出)、scanf(格式输入)、puts(输出字符串)、gets(输入字符串)。

(1)printf函数的格式为【printf(格式控制,输出列表)】,格式控制即””中的格式说明。

       ①%d用于以十进制输出int类型数据,对于2个字节的整型,输出范围在-32768-32767。故用其输出不在整个范围的数会出错:long型用%ld,unsignedint用%u

       如unsignedint a=65535;在存储单元中是16个1,对应-1的补码,所以采用%d输出时显示-1。要显示65535要使用%u(用于unsigned型数据的输出)。

       另外%md(m是一个常数)用于指定输出字段的宽度。数据位数小于m则在左边空格补齐,若大于m则按实际位数输出。

       %o,%x用于将存储单元中的二进制码转化成八进制,十六进制输出。忽略符号位。

       ②%c输出字符或者0-255内的正数。%s输出字符串,%ms指定输出的字符串占的列数(不足左边补空格),%m.ns指定占m列但只显示字符串的左边n个字符。

       ③%f输出float、double型数据。%m.nf控制小数点位数。%e以指数形式输出,%g根据数值大小选择%f或%e输出。

       ④printf输出一个“%”要在格式控制中连续使用两个%printf”%%”;

       (2)【scanf(格式控制,地址列表)】,地址列表可以使变量的地址,或字符串的首地址。scanf将输入的数据存放到对应的变量的地址,所以需要“&”取地址符号。

       ①scanf可以指定输入数据长度,系统自动截取所需数据。如scanf(“%3d%3d”,&a,&b);输入123456,系统自动将123赋给a,456赋给b,而不需要在输入的两个数之间输入空格或enter或tab。

       ②在%后加一个“*”,表示跳过它指定的列数。如scanf(“%2d%3*d %2d”,&a,&b);输入12 345 67,将12赋给a,67赋给b,而将345跳过。对于利用现成的一批数据作为输入时,可以跳过不需要的数据。

       ③用%c作为输入格式时,空格和转移字符都作为有效输入。如

       scanf(“%c%c%c”,&a,&b,&c);

       输入1 23

       则结果a=’1’;b=’ ‘; c=’2’;。因为1与2之间的空格作为有效字符输入赋给了b!所以在对一连串用%c输入的字符时,不需要用空格间隔,输入123。或者采用“%c%c %c”,即对输入格式做一定规定。

       scanf和getchar作为输入函数,从键盘输入时,是在按enter键后才将一批数据送到内存缓冲区,然后从缓冲区逐个读取字符输出。对于下面的程序

while(1){

              //scanf("%c",&c);

              c=getchar();

              printf("%c",c);

       }

       当从键盘输入abc后enter,可以输出abc。其原因是getchar将abc都放入了缓冲区,在执行printf时,让c依次成为’a’、’b’、’c’并输出,最后结果显示abc。并非c=’abc’。对程序设置断点可以看出c的值变化。或改成printf("%c\n",c);可以看出abc单独成行输出。

       但c=’abc’;或者不在循环中的c=getchar();键入abc时,c只选取第一个字符。

       对于从文件输入可用EOF结尾标志:while(scanf("%d%d",&a, &b) != EOF)

11、类型转换:不论是long转int,int转char,signed转unsigned,都是按存储单元中的储存形式直接传送给目标类型。长转短取低位,短转长高位补0或1(负值int转long高位补1以保持数值不变)。转化关系如下(“←”表示必定会转化,即两个float数参与运算也会先转化为double型)

double ← float 高

long

unsigned

int ←char,short 低

想要计算得到浮点数据,不能是1/2*(3.0+4+5),更不是1/2*(3+4+5) 尽管第一个式子有浮点型数据3.0,但是表达式先计算1/2,并且以整型计算,并不会将1/2转化为double计算得到0,以最后结果是0.000000。正确的表达式为1.0/2*(3+4+5)

12、布尔型

c89标准没有布尔型,在c99标准中加入了bool的布尔型变量,导入<stdbool.h>头文件即可。但参照标准的不同,有的编译器不包含该头文件。此时可以下载头文件并导入工程,或者采用宏定义:

#define boolint

#define true 1

#define false0

可以使用bool b=true;定义变量。

       故C中用1表示真,0表示假。if语句中关系表达式的结果用1或0表示。对于常量,0表示假,非0表示真(不论正负)。故(a>b)>(b>c)这样的语句是正确的,也可以对一个关系表达式用%d输出(1或0)。

       参与逻辑运算(与或非)的对象可以是0或非0的整数,也可以是字符型、实型、指针型。C中的&&、||也有在“判断终止性”,即&&中有一个是假(或||中有一个是真)即停止后续判断。

13、条件表达式【表达式1?表达式2:表达式3】从右至左结合。当表达式2和表达式3类型不同时,不管选用表达式2还是表达式3的结果,都转化为等级高的类型。如

       x>y?1:1.5;x<=y时,取1.5;若x>y则取1.0。

并且表达式1、表达式2、表达式3都是被求职,并不是在取值的时候才求值,而不取值就不求值了!所以下面的表达式

int a=2,b=2,c=3;

int d= a++ > b ? a :c++;

运行后a=3;b=2;c=4;

并且若int d= a++ > b ? a :a++;则a会被自加两次!这经常在宏定义里会被误用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值