无偿分享学习资料,需要的小伙伴评论区或私信dd。。。
无偿分享学习资料,需要的小伙伴评论区或私信dd。。。
无偿分享学习资料,需要的小伙伴评论区或私信dd。。。
完整资料如下:纯干货、纯干货、纯干货!!!
常量
定义:程序运行过程中,值不能被改变的量就是常量(变量值)
分类:整型常量、实型常量、字符常量、字符串常量、符号常量
整型常量:包括正整数、0、负整数。整型常量可以使用八进制、十进制、十六进制表示
-
八进制:以0为前缀(可省略),由数字(0~7)组成,没有负数
-
十进制:负数、0、正数
-
十六进制:以0x或0X为前缀(可省略),由数字(0~9)和字母(A~F)组成,没有负数
⚠️注意:整型常量默认为int类型(但是会根据数值的大小去判断其类型),在后面加上字母可转变为其他整型类型,但是不允许加h和uh表示short和unsigned short。
原类型 | 新类型 |
---|---|
l或L | long |
ll或者LL | long long |
u | unsigned int |
ul | unsigned long |
ull | unsigned long long |
实型常量:实数,又称浮点数。表示方法分为:小数形式、指数形式
-
小数形式:由整数部分、小数点、小数部分组成。小数点前后为0时可以省略,但是要保证至少一边要有数字,且小数点不可省略
-
指数形式:由尾数部分、e(E)、指数部分组成。e(E)前面必须有数字(整数小数皆可)、后面必须为整数(正负零皆可)
⚠️注意:c语言中。实型常量默认为double类型常量,只有在数字后面加上f或F才认为是float类型。
printf("%d\n",sizeof(1.34));//1.34默认是double类型,所以输出8 printf("%d\n",sizeof(1.34f));//1.34f是float类型,所以输出4 float a=1.34;//此时1.34默认为double类型,但是变量a是float类型,所以这里会进行自动类型转换,将double类型转换为float再赋值给a printf("%d\n",sizeof(1.34));//所以这里直接输出1.34结果依然是double类型 printf("%d\n",sizeof(a));//这里输出a就是输出a保存的值1.34,此时1.34已经从double类型自动转换为float类型保存在a中, //所以输出4
double类型常量小数形式要求小数点不能省略,但是在赋值时实际会进行自动类型转换,所以double类型可以赋值一个整型省略小数点
double x=3;//等价于double x=3.
指数形式e后面的数值为十进制数。
字符常量:有两种字符常量:普通字符、转义字符
-
普通字符:使用单引号阔起来的一个字符,例如'a'。字符常量只能使用单引号括起来,且只能是一个字符,不能是字符串。注意单引号只是界限符,故字符常量不包括单引号。字符常量区分大小写,故大小写字母是两个不同的字符常量。字符常量存储在内存中存放的是其ACSII码值(以二进制形式存放),一个字节常量占有1个字节。
-
转义字符:使用单引号阔起来的以\开头后面跟一个字符或用八进制、十六进制表示的ASCII码值
char a,b,c; a='\n';//换行 b='\141';//八进制字符a c='\x61';//十六进制字符a(x后面只有1~2个十六进制数字)
⚠️注意:转义字符中的八进制、十六进制区别在于十六进制以“\x"开头(注意x不要大写),且八进制 \ 后最多三位数字,十六进制
\x 后面最多两位数字。
b='\141';//八进制 c='\x61';//十六进制
字符串常量:使用双引号阔起来的若干字符。字符串常量不能使用单引号阔起来。字符串常量中可以使用空格、转义字符、汉字等其他语言文字;n个字符组成的字符串在内存中占n+1个字节空间。字符串的长度由其双引号内的字符个数决定,若是遇到\0则认为字符串结束
-
使用sizeof运算符计算字符串占用的内存空间,sizeof的参数可以是常量、变量、数据类型。
char str[]="ab\0c"; printf("%d\t%d\n",sizeof("ab\0c"),sizeof(str));//5 5(sizeof遇到\0不会认为字符串结束,会将\0作为一个字符处理最后结尾再自动加上一个\0。)
-
sizeof运算符不会因为字符串的末尾有\0而不自动加上\0(即认为本身存在的\0是一个字符)。
char str[]="hello\0"; printf("%d",sizeof(str));//7
-
使用strlen()函数计算字符串的长度
printf("%d\n",strlen("hello"));//5 printf("%d\n",strlen("h\0ello"));//1
⚠️注意:使用strlen函数需要使用#include <string.h>把该函数的信息引入源程序文件才可以使用,而sizeof是c语言自带的运算符
-
c语言没有提供字符串变量。
-
c语言有空串(占一个字节),但是没有空字符。
char str[]=""; printf("%d\t%d\n",sizeof str,strlen(str));//1 0 char a='';//报错!注意不要与 char a=' '混淆,单引号中间有一个空格,ASCLL码值为32
-
c语言不允许对字符串直接使用关系运算符,但是可以通过strcmp函数进行比较。
字符常量与字符串常量有什么区别:
-
字符常量使用‘’单引号扩起来,字符串常量使用“”双引号扩起来。
-
字符常量只能是单个字符,字符串常量可以是多个字符。
-
字符常量存储的ASCLL码,一个字符占用一个字节内存,字符串常量在内存中占用一段连续的存储单元,一个字符占用两个字节内存
-
可以把一个字符常量赋值给一个字符变量,但是不能把一个字符串常量赋值给一个字符变量。
符号常量:使用 #define 指令,指定一个符号名称代表一个常量。
格式:#define 标识符 常量值
-
#define是预处理命令(宏定义命令)。一个预处理命令只能定义一个符号常量。且它不属于c语言中的语句,所以不能加分号。
-
符号常量不占用内存空间,在预编译之后就会销毁,所以程序运行过程中不允许对符号变量赋新值。
-
为与变量区别,符号常量一般采用大写字母表示。
-
符号常量指定的标识符与数值中间必须有一个空格(#define x (12,2)也是对的,只要中间有空格)
使用符号常量的好处
-
含义清楚,程序中用到的符号常量的作用一目了然,且能做到一改全改。
-
增加程序的可读性,提高程序的可维护性。
-
简化代码、方便数组定义。
变量
定义:程序运行过程中,其值可以改变的量就是变量
⚠️注意:变量必须先定义后使用,变量代表一个有名字、具有特定属性的一个存储单元,它用来包存数据。变量名实际上是一个符号地址,程序编译时由系统给变量分配一定的存储空间,程序运行过程中通过变量名找到相应的内存地址对其中的数据进行读取与操作。
变量定义
格式:类型说明符 变量名; 例如 int a; 1.定义多个变量使用逗号隔开 int a,b; 2.变量名必须是合法的标识符。 3.变量必须先定义再使用。 4.类型说明符必须是合法的数据类型标识符。
变量的初始化
定义:c语言允许在定义变量的同时对变量赋值,这个过程称为变量的初始化
int a=1,b=1或int a=1;int b=2;//初始化 1.不允许对多个未定义的变量赋初值 int x=y=3;//x、y正在定义,还没有成功定义,不允许同时初始化 应该这样初始化 int x,y; x=y=3;//x、y上面已经定义,允许同时初始化 2.初始化保证=两边的数据类型一致,否则系统会进行自动转换赋值(把=右边的数据类型转换为与左边的一致) 3.未初始化的变量其值是未知的(全局变量或static局部变量未初始化默认为0或'\0')
⚠️注意:动态变量的初始化是在程序运行时执行到此变量的赋值语句才初始化。静态存储的变量和外部变量是在编译阶段就初始化了
变量的引用
定义:对变量的访问分为直接访问(变量名)和间接访问(地址 / 指针)。
变量类型与变量的区别:
变量占据存储内存,是具体存在存在的实体,而类型是变量的属性,是抽象的,不占据内存空间。
常变量
定义:在定义变量时前面加一个 const关键字,常变量的值不允许改变
常变量与常量的不同
常变量是有名字的不变量,而常量是没有名字的不变量,有名字就便于在程序中引用。
常变量与符号常量的不同
-
符号常量使用 #define 定义,它是预编译命令。而常变量使用const关键字定义。
-
符号常量不占用内存空间,其在预编译阶段进行字符替换,预编译之后就会销毁。而常变量占用内存空间,其是在编译阶段才进行内存分配。
⚠️注意:常变量与符号常量都不允许赋新值
标识符
定义:用来标识变量、函数、类型和语句的符号就是标识符。
规定:标识符只能由“数字、字母、下划线构成,且第一个字符不能是数字。
分类:关键字、预定义标识符、用户自定义标识符。
-
标识符区分大小写。关键字是系统定义的有特殊含义的标识符,用户自定义标识符号不允许与其重名。预定义标识符是一些头文件中的标识符,c语言允许用户自定义标识符与其重名,但是会使其失去原有的含义,应避免这样做。
-
c语言允许形式参数与函数名重名(允许本函数内的局部变量与本函数同名),即不允许在相同作用域内出现相同的标识符。
int sum(int sum,int y){ return 0; }
-
main也可以做变量名。
数据类型
定义变量为什么指定数据类型?
计算机的存储单元是由有限的字节构成的,每一个存储单元存放数据的范围是有限的,而不同的数据类型在计算机内存中占用不同大小的存储单元,系统在编译时要根据类型去开辟相应大小的空间去存储数据,且存储形式也各不相同。
数据类型的分类
基本数据类型:整型、实型、字符型。
枚举类型(enum)
空类型(void)
派生类型:指针类型、数组类型、结构体类型、共用体类型、函数类型。
-
基本类型与枚举类型统称为算数类型,因为他们变量的值都是数值。算数类型与指针类型统称为纯量类型,因为他们变量的值是用数字来表示的。数组类型与结构体类型统称为组合类型,注意共用体不属于组合类型,因为同一时间内只有一个成员具有值。
-
双长整型(long long)和bool是c99后面增加的。使用bool类型需要加上头文件<stdbool.h>才可以正常使用bool类型。
整型数据类型
分类:short int、int、long int、long long int、unsigned short、unsigned int、unsigned long、unsigned long long
占有字节与取值范围:
类型 | 字节 | 取值范围 |
---|---|---|
short int | 2 | -215~215-1 |
int | 4(2) | -231~231-1 |
long int | 4 | -231~231-1 |
long long int | 8 | -263~263-1 |
unsigned short | 2 | 0~216-1 |
unsigned int | 4 | 0~232-1 |
unsigned long | 4 | 0~232-1 |
unsigned long long | 8 | 0~264-1 |
1.有符号整型数据在内存中以二进制的补码的方式的存储
正数的补码:其二进制形式
负数的补码:其正数的二进制形式按位取反加1
⚠️注意:在存放有符号整型的存储单元中,最左边的一位表示符号,0表示正,1表示负。
2.无符号整数以二进制的原码存储
-
c没有具体规定各种类型所需分配的字节,只要求short<=int<=long<=long long。在Turbo C 2.0中,为每个int类型只分配2个字节。
-
sizeof运算符不仅可以测量变量值的占有空间大小,还可以测量数据类型占有空间大小。sizeof的参数可以是常量、变量、数据类型。
char str[]="hello"; printf("%d\n",sizeof(str));//变量值hello占有6个字节 printf("%d\n",sizeof(char));//char占有1个字节
-
无符号整型直接存储其二进制(二进制的原码),其存储单元中全部二进制位都用来存储数值,所以最左边没有符号位,取值范围自然也扩大一倍
-
无符号整型的输出与输入采用“%u(lu、hu、llu)”格式。
-
只有整型与字符型数据可以加signed与unsigned。
-
整型常量默认为int类型,但是会根据数值的大小判断其具体是什么类型。
printf("%d\n",sizeof 32767);//4 printf("%d\n",sizeof 327679999999999);//8(超出了int的取值范围)
字符型数据类型
分类:char、unsigned char
占有字节与取值范围:
类型 | 字节 | 取值范围 |
---|---|---|
char | 1 | -27~27-1 |
unsigned char | 1 | 0~28-1 |
-
字符型数据在内存中实际存储的是其ASCII码值,所以与int相同以二进制的补码在内存中存储。但是ASCII码值没有负值,虽然允许存储的值为-128~127,实际上用到的只有0~127这个范围,所以char类型的最高位符号位一般都是0(int等最高位是有变化的)。
-
无符号char在内存中与int等无符号整型一样也是直接存储二进制(二进制的原码),但实际上用到的也只有0~127这个范围。
-
字符型数据可以参加算数运算,其计算的是其ASCII码数值
-
c语言允许对整型变量赋予字符值,允许对字符变量赋予整型值(应在0~127范围内);同时允许字符数据按整型输出,也允许整型变量按字符量输出((应在0~127范围内)
//允许对整型变量赋予字符值,允许对字符变量赋予整型值; char a=65; int b='A'; printf("%c%d\n",a,b);//A,65 //同时允许字符变量按整型输出,也允许整型变量按字符量输出 char c='A'; int d=65; printf("%d%c\n",c,d);//65,A
-
ASCLL码值常见 数字<大写字母<小写字母
实型数据类型
分类:float、double、long double
占有字节与取值范围:
类型 | 字节 | 取值范围 |
---|---|---|
float | 4 | 3.4E-38~3.4E+38 |
double | 8 | 1.7E-308~1.7E+308 |
long double | 8(16) | 1.7E-308~1.7E+308 |
-
在c语言中,实型数据是以二进制的指数形式存放在存储单元的,存储时,系统将浮点数据拆分为小数部分与指数部分,小数点移至最前面,指数部分10的幂次由小数点前移位数决定。
3.14159在内存中为:符号位 .314159 1 =+0.314159E1
-
float类型只能得到6~7位有效数字。double类型只能得到15~16位有效数字,但是小数位最多保留6位,其余四舍五入。
float a=1234.5678999; double b=1234.567895678; printf("%f\n%f\n",a,b); /* 输出:1234.567871 1234.567896 float a只能保留6位有效数字,其整数位占4位,所以小数位只有2位有效。以%f格式输出会整数取完,小数取6位。 double b虽然有15位有效数字,但是小数位只能保留6位 */
-
实型常量都默认为double类型,只有在数字后面加上f或F才认为书float类型。c语言在进行浮点数运算时,将float类型都自动转换为double类型(自动类型转换)
-
实型常量后面加L表示long double类型。
-
在Turbo C中对long double类型分配16个字节
-
实型常量不能准确的表示一个实数,因为在有限的存储单元中,必然会造成精度丢失。
运算符与表达式
c运算符的分类:
算数运算符 | (+、-、*、/、%、++、--) |
---|---|
关系运算符 | (>、<、==、>=、<=、!=) |
逻辑运算符 | (!、&&、||) |
赋值运算符 | (=、+=、-=、/=、*=、%=) |
条件运算符 | (?:) |
逗号运算符 | (,) |
指针运算符 | (*、&) |
求字节数运算符 | (sizeof) |
强制类型转换运算符 | ((类型)) |
下标运算符 | ([]) |
成员运算符 | ( . , —>) |
位运算符 | (~,&、|、^) |
其他 | (如函数调用运算符(),同时也是括号运算符) |
-
sizeof是单目运算符,优先级高于双目运算符。sizeof运算符()也可以省略不写。
-
c运算符的功能:
- 用于对各种数据类型进行运算。
- 将运算对象连接组合成各种表达式。
1.算数运算符
分类:+(加、正)、-(减、负)、*(乘)、/(除)、%(余)、++、--
-
+、-表示正负时是 单目运算符,表示加减为双目运算符。++、--也是单目运算符。除此之外其他算数运算符都是双目运算符
-
在计算a/b时,如果ab都是整型,那么其商也是整型(若其中有一个负数则结果为负数,两个都为负数则为正数)。如果ab其中一个位实型,则ab都转换为double类型,结果为double类型
printf("%d\n",(5/3));//1 printf("%d\n",(-5/3));//-1 printf("%d\n",(5/-3));//-1(注意) printf("%f\n",(5/2.0));//2.500000
-
在计算a%b时,要求ab都是整型,其结果也是整型,结果的符号与a的操作符号相同,除%之外其他算术运算符可以是任意合法的算术类型。
printf("%d\n",(10%3));//1 printf("%d\n",(-10%3));//-1
-
注意:0 做第一个操作数%(*/) 任何数值 =0。0不能做第二个操作数,否则会造成运算溢出。其结果是一个不确定的数值,0做被乘数是0。
//0做第1个参数都是0 printf("%d\n",0*3);//0 printf("%d\n",0/3);//0 printf("%d\n",0%3);//0 //0做第2个参数都是0 printf("%d\n",3*0);//0 printf("%d\n",3/0);//警告且结果随机( printf("%d\n",3%0);//警告且结果随机
-
注意:变量的初始化=右边的常量允许与=左边的类型不一致(会自动转换),但是在printf输出时,如果输出的数据的类型与输出格式不一致会输出不正确的结果。
int a=100.1; printf("%f\n",a);//0.000000
++i与i++的区别:
i++,i--:先赋值,再自增(减);++i,--i:先自增(减)再赋值
int main(){ int i=3; int a=i++;//i=4 int b=i--;//i=3 int c=++i;//i=4 int d=--i;//i=3 printf("%d%d%d%d\n",a,b,c,d);//a=3、b=4、c=4、d=3 return 0; }
-
++、--属于单目运算符,操作对象只能是一个简单的变量,不能是常量或表达式。例如6--、(a+b)++就是错误的
-
自增自减在同一作用域任何地方出现都会在这个作用域范围内自增或自减
int a=1; printf("a=%d\n",--a);//a=0 //a=--a,此时a值为0 printf("a=%d\n",a--);//a=0 //a=a--,此时a值为-1
-
实型数据也可以++、--。
-
(a++)++是不合法的表达式。
算数运算符的优先级与结合性:
优先级:(正+、负-、++、--)>(*、/、%)>(加+、减-)【即单目运算符优先级>双目运算符】
结合性:(正+、负-、++、--):右结合 【即单目运算符(右结合:自右向左)】
(*、/、%)、(加+、减-):左结合 【即双目运算符(左结合:自左向右)】
-
优先级相同的条件下按照结合型处理
算数表达式:
定义:使用算数运算符和括号将运算对象(可以是常量、变量、函数、表达式等)连接起来的合法表达式就是算数表达式。
-
一条c语句可以写在一行或多行,但是算数表达式只能写在一行。
2.赋值运算符
分类:=、+=、-=、*=、/=、%= 等(赋值运算符+复合赋值运算符)
-
在复合赋值运算符中,例如 a%=b ,如果b是一个表达式,那么相当于有括号
x%=y+3;//等价于 x=x%(y+3)
-
凡是二元运算符,都可以与赋值运算符一起则合成复合赋值运算符。
-
使用复合赋值运算符的好处
- 简化程序,使程序更精炼。
- 提高编译效率,产生质量较高的目标代码。
赋值运算符的优先级与结核性
赋值运算符都是双目运算符,它们优先级相同,且都属于右结合。(⚠️注意:一般情况双目运算符都属于左结合)
赋值表达式
定义:使用赋值运算符将变量与表达式连接起来的式子就是赋值表达式
格式:
变量 赋值运算符 表达式(一般为算数表达式和常量) 左值 右值 1.凡是左值都可以做右值 2.左值应该是一个可修改的值(必须为变量)
作用:将一个表达式的值赋值给一个变量(具有赋值与计算的双层功能)
-
赋值表达式的左边必须是一个变量。例如 3=x、a+b=2、(a=b)=c=6都是错误的赋值表达式
-
赋值表达式右边的表达式也可以是一个赋值表达式
a=b=3
-
赋值表达式出现在任何优先级比他高的运算符(关系运算、算数运算、条件运算、逻辑运算等)两侧时要加括号
赋值语句
定义:赋值表达式+;就构成了赋值语句
1.赋值表达式与赋值语句的区别:
赋值表达式末尾没有分号,而赋值语句末尾必须有分号,在一个赋值表达式中可以包含多个赋值表达式,但是绝不能包含赋值语句。
赋值过程中的类型转换
规则:=两边类型相同的情况下直接赋值,不同的情况下将=右边的类型转换为左边的类型再赋值(前提是高字节不超出低字节的范围,否则无法输出正确信息)
赋值转换表达式 | 转换过程 |
---|---|
整型 = 实型 | 舍去小数位,只取整数位 |
实型 = 整型 | 先将整型转变为实型再赋值 |
float = double | 先将double转变为float(即只取6~7位有效数字)再赋值 |
double = float | 数值不变,在内存中以8个字节存储,有效位数扩展到15位 |
整型 = 字符型 | 将字符型的ASCLL码赋值给整型 |
... | ... |
截断:高字节整型数据赋值给一个低字节整型数据,只将低字节部分原封不动的送到赋值变量称为截断。
失真:高字节整型数据赋值给一个低字节整型数据,超出了低字节的最大取值范围称为失真。
-
在给一个变量赋值时,所以也可以不指定变量值(常量)的数据类型,因为系统会自动进行自动类型转换
float a=1.34f;//1.34虽默认为double类型,但是变量a是float类型,所以会自动转换为float类型再赋值给a
3.关系运算符
分类:<、<=、>、>=、==、!=
关系运算符的优先级与结合性:
优先级:(<、<=、>、>=)>(==、!=)
结合型:左结合【双目运算符:左结合】
-
优先级相同的条件下按照结合型处理
-
关系运算符都是双目运算符(优先级:算数运算符>关系运算符>赋值运算符)
-
对实数进行相等判断可能得不到正确的结果。例如 1.0/3*3.0==1.0 的结果为0
关系表达式:
定义:使用关系运算符将两个数值或表达式连接起来的式子是关系表达式
-
关系表达式的值为逻辑值,在表示(结果)上:1【真】、0【假】。在判断上:非零【真】、零【假】
-
关系表达式的两边也可以是一个赋值表达式,因为关系表达式优先级大于赋值表达式,所以需要用括号把赋值表达式括起来,此时拿赋值表达式右边的数值与关系表达式左边的表达式比较
int a; (a=3)==(a=3); printf("%d\n",a);//3就是数值3。a=3结果为数值3。所以3=3,结果a=1
-
关系表达式的值是逻辑值,但是切记c语言没有逻辑类型。
4.逻辑运算符
分类:&&(AND)、||(OR)、!(NOT)
逻辑运算符的优先级与结核性
逻辑运算符 | 优先级 | 结合型 | 含义 |
---|---|---|---|
!(非) | 1 | 右结合(单目运算符) | 取反 |
&&(与) | 2 | 左结合(双目运算符) | ab都为真则为真,否则为假 |
||(或) | 3 | 左结合(双目运算符) | ab其中一个为真则为真,二者都为假才为假 |
-
&&、||优先级低于关系运算符(算数运算符>关系运算符>逻辑运算符>赋值运算符)。!优先级大于算数运算符中的双目运算符。
-
BASIC与Pascal等语言可以直接使用AND、OR、NOT。
逻辑表达式
定义:使用逻辑运算符将关系表达式或算数表达式等合法表达式连接起来的式子就是逻辑表达式
-
逻辑表达式的值为一个逻辑值,在表示上:1【真】、0【假】。在判断上:非零【真】、零【假】。
-
短路:计算出左边第一个表达式的值就可以确定整个表达式的值称为短路(对于||来说左边第一个为真时则不必计算右边的表达式。对于&&左边第一个为假时则不必计算右边的表达式)
-
当出现短路现象,右边的语句不会被执行
int a; (3<2)&&(a=3>2); printf("%d\n",a);//输出一个随机数,因为右边的赋值没有执行
-
逻辑表达式的两边也可以是一个赋值表达式,因为逻辑表达式优先级高于赋值表达式,所以赋值表达式需要加括号,此时拿赋值表达式右边数值的逻辑值与逻辑表达式左边的表达式对比
int a; a=(3>2)&&(a=3); printf("%d\n",a);//3>2为真,a=3值为3,即(3)非零所以也为真,那么结果a=1
5.条件运算符
格式:表达式1 ?表达式2 :表达式3
-
条件运算符是c里面唯一的三目运算符
-
条件运算符优先级高于赋值运算符(算数运算符>关系运算符>逻辑运算符>条件运算符>赋值运算符)
-
条件运算符为右结合(但是计算顺序为从左向右)
条件表达式
定义:由条件运算符将三个表达式连接起来的式子称为条件表达式。
-
条件表达式没有执行的表达式对其他数据不产生影响
int a=1,b=2,c; (a<b)?(c=a+1):(c=b=3); printf("a=%d,b=%d,c=%d\n",a,b,c);//a=1,b=2,c=2.因为表达式3没有执行
-
条件表达式的结果根据表达式1的真假来选择是表达式2还是表达式3,结果的类型由表达式2与3中类型较高的决定
printf("%d\n",12?1:3.0);//编译时系统会提醒报错,且输出结果为0,可见结果并不是int类型 printf("%f\n",12?1:3.0);//改为f之后,输出结果就没有报错,此时为1.000000
-
条件表达式中出现赋值表达式应该使用括号括起来,因为条件运算符优先级高于赋值运算符。例如a>b?(a=2):(a=1)。
-
条件表达式出现在逻辑运算符、关系运算符、算数运算符等比他优先级高的运算符两侧时要加括号(根据需要)
-
条件运算符允许嵌套,嵌套时候从右往左以?与:为一对划分(右结合)。例如 a>3?b:c>2?1:0 等同于 a>3?b:(c>2?1:0)。
-
条件表达式可以出现在printf语句中
printf(2>1?"%c":"%d",97);
6.逗号运算符
格式:表达式1,表达式2,...,表达式n
作用:用于对各种数据类型进行运算,并连接运算对象组合成逗号表达式。
-
逗号运算符是双目运算符(左结合),但是其优先级最低(故不存在双目运算符优先级大于三目运算符)
-
并非所有出现逗号的地方都是逗号表达式。
逗号表达式
定义:使用逗号运算符将多个表达式连接起来的表达式称为逗号表达式。
-
逗号表达式的结果为最后一个表达式的值,但是前面的表达依然成立。
int a,b,c,d; d=(a=1,b=2,c=3); printf("%d %d %d %d\n",a,b,c,d);//1 2 3 3 可见前面的 a b c 都被赋值成立。 注意:以下程序段不等价于上面程序段 int a,b,c,d; d=a=1,b=2,c=3;//因为,运算符优先级低于赋值运算符,所以计算完 a=1后直接将1赋值给d。 printf("%d %d %d %d\n",a,b,c,d);//1 2 3 1
-
不是所有出现逗号的地方都是逗号表达式。如在多个变量定义、函数参数等只是一个分隔符
7.位运算符
分类:&、|、^、~、>>、<<
-
左移右移不影响原数据的值。
int a=8; a>>2; printf("%d\n",a);//8
位运算符的优先级与结核性
运算符 | 优先级 | 结核性 | 操作 | 含义 |
---|---|---|---|---|
~ | 1 | 右结合 | 1变0—0变1 | 按位取反 |
<< | 2 | 左结合 | 高位舍去,低位补0 | 左移1位 |
>> | 2 | 左结合 | 无符号数-低位省去,高位补0。有符号数-低位省去,高位结果为正补0,为负补1 | 右移1位 |
& | 3 | 左结合 | 两个都为1才为1 | 按位与 |
^ | 4 | 左结合 | 两个相同为0,不同为1 | 按位异或 |
| | 5 | 左结合 | 两个都为0才为0 | 按位或 |
-
~运算优先级最高,<<>>运算符在算数之后,关系之前。&、|、^在关系之后、逻辑之前。
-
左移动一位相当于✖️2,右移1位相当于/2。(奇数右移时这种方法不行)
-
优先级相同的条件下按照结合型处理。
-
不同大小的数据位操作的原则,低位对齐,高位补零。
例如11和101将11转变为011再和101运算 011 101 ————
不同类型数据之间的混合运算
简述:c语言规定:各种不同数据类型之间进行运算时,不同的数据类型必须转换为相同的数据类型才能进行运算,可分为以下两类。
1.自动类型转换
定义:不同数据类型的数据进行混合运算时,会先进行自动类型转换。
规则:【低字节--->高字节 / 有符号--->无符号】
-
只要其中一位操作数为实型(不管是float还是double),那么两个操作数都转换为double类型,结果为double类型。哪怕两个float类型也要转换为double类型。
-
其余整型与字符类型是取字符型的ASCII码计算,结果可以为整型、也可以为char类型
2.强制类型转换
定义:将表达式结果的数据类型强制转换为需要的数据类型
格式:(数据类型)(表达式)
-
表达式可以是一个变量名(将变量强制转换成需要的数据类型)或者一个算数表达式(将计算结果强制转换成需要的数据类型)
-
表达式一定要用括号括起来,否则只对强转符后面的量强制转换。
(int)x+y;//只把x强转为int类型,而不是x+y
-
强制转换只会生成一个临时值,不会改变原有数据的类型和值,该临时值在赋值后就会销毁。
float x=1.34; int y=(int)x; printf("x=%F\n",x);//x=1.340000 printf("y=%d\n",y);//y=1
-
从高字节类型转换为低字节类型会造成精度丢失。
-
强制转换不属于常量。例如:(long)123 不属于常量。
c语句的作用与分类
作用:向计算机系统发出指令操作,执行相应的操作(一个c语句在编译后产生若干条机器指令)
-
声明部分不属于语句,因为他不会产生机器指令(个人认为声明属于声明语句,也属于语句,会在系统中开辟内存空间,只是不执行具体操作)
-
c语句必须以分号结尾,但是复合语句不用。
分类:
-
控制语句:(9种)
- if ()... else...
- for()...
- while()...
- do...while()
- continue
- break
- switch
- return
- goto
-
函数调用语句:由函数调用表达式加上一个分号构成。
-
表达式语句:表达式加上一个分号构成。
-
空语句:一个分号(;),什么也不做。
-
复合语句:使用{}将若干条语句括起来就构成了复合语句(又称语句块)。
c程序中,最常用的语句是赋值语句和输入输出语句,其中最基本的是赋值语句
数据的输入输出
分类:printf()、scanf()、putchar()、getchar()、puts()、gets()
-
所谓输入输出是以计算机主机为主体而言的,从计算机向输出设备(如显示器、打印仪)输出数据称为输出,从输入设备(如键盘、光盘、扫描仪)向计算机输入数据称为输入。
-
c语言本身不提供输入输出语句,所有的输入输出都是都是由c标准库函数来实现的。因此要是使用 #include 引入头文件。
-
#include <stdio.h>的执行过程为:程序运行到#include <stdio.h>,去系统子目录寻找到头文件stdio.h,找到后将该头文件中的内容调出来取代本行的#include指令。
-
#include <stdio.h>:调用stdio.h的标准方式,直接从c编译系统的子目录寻找。
#include "stdio.h":先从用户的当前目录寻找,找不到再按照标准方式寻找。
格式字符
格式字符 | 含义 |
---|---|
d、i | 以十进制输入或输出有符号整数(正数不输出符号) |
o | 以八进制输入或输出无符号整数(不输出前缀 0) |
x、X | 以十六进制输入或输出无符号整数(不输出前缀 0x) |
u | 以十进制输入或输出无符号整数 |
f | 以小数形式输入或输出实float(若没有指定m、n,则是整数取完,小数保留6位)。(注意f还可以输出double) |
e、E | 以指数形式输入或输出float。(注意还可以输出double) |
g,G | 以%f或%e中较短的输出宽度输出float、double(不输出无意义的0) |
lf | 以小数形式输入或输出double类型 |
le | 以指数形式输入或输出double类型 |
c | 输入或输出一个字符 |
s | 输入或输出一个字符串 |
-
x和X的区别在于:使用x输出的十六进制数中a~f为小写字母,X为大写字母。
-
e和E的区别在于:使用e输出的实数指数形式使用小写字母e表示,E使用大写字母E表示。
-
以e格式输出时如果不指定m、n,默认实数整数部分占1位(注意整数部分为非零值),小数点1位、小数部分占6位(多余四舍五入),指数部分占5位(符号1位,e1位,指数3位),共占13列宽度。
printf("%e\n",31.234476744); //输出:3.123448e+001 printf("%e\n",01.234476744); //输出:1.234477e+000
-
除了X、E、G外其他格式字符必须使用小写字母。
-
%o与%x格式输出时,默认输出的数值不带前缀0与0x,如果需要前缀则需要加上#修饰符。且八进制与十六进制没有负数,输出一个负数时实际上是按位取反+1。
格式修饰符:
格式修饰符 | 含义 |
---|---|
l | 输入或输出long类型,可以加在d、o、x、u、i前面 |
ll | 输入或输出long long类型,可以加在d、o、x、u、i前面 |
h | 输入或输出short类型,可以加在d、o、x、u、i前面 |
m | 指定数据的输出、输出宽度。若实际宽度大于m则按照实际宽度输出;若实际宽度小于m且m前面有-则左对齐右补空,反之则默认右对齐左补空(指定数据的输入宽度) |
n | 指定实数的小数位数(若为0则不输出小数位与小数点,只能用于实型) |
- | 输出结果左对齐右补空(默认右对齐、左补空) |
+ | 输出结果加上符号(正或负) |
* | 本输入项不会赋值给相应变量(scanf),默认跳过1列 |
# | 八进制、十六进制输出加前缀(放在o、x前面) |
-
m、n在输出时可以控制数据的宽度与精度。m在输入时还可以控制数据的截取列数而不使用分隔符连续输入。
scanf("%2d%2d",&a,&b);//若输入1234,则a=12,b=34 scanf("%3lf%3lf",&a,&b);//若输入1.23.4,则a=1.200000,b=3.400000 scanf("%2c%3c",&a,&b);//若输入howareyou,则a=h,b=w scanf("%2d%4f%2c",&a,&b,&c);//若输入123.14ok,则a=12,b=3.14,c=o
-
如果m为0则整数位取实际位数输出,对于实型数据若n为0,则不仅不输出小数,连小数点都不会输出。(不建议这样使用)
printf("%0d\n",12);//12 printf("%3.0f\n",12.34);// 12(注意12前面有一个空格) printf("%0c\n",'a');//a printf("%.3f\n",12.34);//12.340
-
m.n 在输出实型数据时,如果实际位数大于m则按照实际位数输出,反之则右对齐左补空,对于n来说如果大于n则四舍五入,小于n则补0。
-
*与m组合可以在输入数据时候跳过相应列个字符。
scanf("%c%*3c%c",&b,&a);//输入:12345 printf("%c",a);//输出:5
1.printf()函数(格式化输出)
格式:printf(" 格式控制字符串 " , 输出表列)
作用:向终端(屏幕)格式化输出数据
-
格式控制字符串表示数据输出的格式,输出表列则是要输出的数据。
-
格式控制字符串包括格式控制说明与普通字符,格式声明有包括%与格式字符,作用就是控制数据的输出格式,以说明数据的类型、形式、长度、小数位数等。普通字符是原样输出的字符。
-
输出表列是需要输出的数据,可以是多个,每个对应着前面的格式字符输出。输出表列可以是常量、变量或表达式。
-
一般情况下printf的格式字符与输出表列是对应的。如果格式字符多于输出表列个数,则多余的格式字符输出不确定的数值。相反则不输出多余的数据。
printf("%d\t%d\n",12);//12 -1983544220(随机值) printf("%d\n",12,13);//12(多余的输出项13不会被输出)
-
printf函数可以没有输出项,但是必须有格式控制字符串,此时用于输出一个字符串。也可以有多个输出项,多个输出项用逗号隔开。如输出项是表达式,那么先计算表达式的结果再输出。
-
若要使用printf函数中输出%,使用%%输出。
-
使用printf函数必须保证格式字符与输出项数据类型一致,否则无法输出正确信息。(不会自动转换类型)
printf("%d\n",1.34);//-687194767
2.scanf()函数(格式化输入)
格式:scanf(" 格式控制字符串 " , 输入项表列)
作用:格式化输入数据(键盘)
-
格式控制字符串表示数据输入的格式,输入项表列则指出数据保存到变量的地址。
-
格式控制字符串包括格式控制说明与普通字符,格式声明有包括%与格式字符,作用就是控制数据的输入格式,以说明数据的类型、形式、长度、小数位数等。普通字符是原样输入的字符。
-
输入项表列应该是变量地址,而不是变量名。(&是取地址符,放在变量名之前表示变量的地址)
-
scanf要求输入参数必须和格式控制字符串中的格式控制说明相对应,并且他们的个数、类型、和位置都要一一对应。
-
scanf函数理论上要求格式字符与输入项的数据类型、个数必须一一对应。如果格式字符大于输入项,则编译时候多余的数据由于找不到保存地址而报错。格式字符少于输入项,则多余的输入项不会被赋值(这点与printf函数区别,printf只要求类型一致)。
int a,b; char c,d; //格式字符多于输入项,报错! scanf("%d%d%d",&a,&b);//警告 printf("%d%d\n",a,b); //格式字符少于输入项 scanf("%d",&a,&b);//只对a赋值 printf("%d%d\n",a,b);//b输出一个不确定的值
⚠️注意:
- 对于整型、实型来说,scanf默认以空格、回车、制表符(tab)分隔。但是在不给分隔符默认情况下,char类型需要与前面的数据一起连续输入。
scanf("%d%d%d",&a,&b,&c);//输入11 12 13(abc都是int类型) scanf("%d%f%c",&a,&b,&c);//输入11 1.34c(a是int,b是double,c是char)。 /*这里注意char类型在和其他数据类型连续输入若格式字符前面没有空格,则需要与前面的数一起连续输入*/
- 在单个输入数据时,如果遇到空格、回车、Tab键,非法输入、指定宽度则认为输入数据结束。
- 输入数值数据时,一般采用逗号、空格、回车来分隔数据。(默认分隔符:空格、回车、制表符(tab))
- char类型与其它类型混合输入若没有指定分隔符,则该char类型需要与前面的数据一起连续输入,其后面的不是char的数据可以与char类型一起连续输入也可以加默认分隔符(只有空格的情况才可以,其他自带的分隔符就不可以)。
scanf("%d%c%f",&a,&b,&c);//没有指定分隔符,则正确输入为:11c1.34或11c 3.14或11c<CR>3.14或11cTAB3.14 scanf("%d,%f,%c",&a,&b,&c);//指定分隔符,则以分隔符输入,正确输入为:11,1.34,C scanf("%c %c %c",&a,&b,&c);//输入123或者 1 2 3都可以 scanf("%c,%c,%c",&a,&b,&c);//必须输入 1,2,3
- char类型在连续输入时候如果没有指定分隔符,则不加任何分隔符(连续输入)。若指定空格为分隔符则加不加分隔符都可。一般以连续输入为准。
char a,b,c; scanf("%c %c %c",&a,&b,&c);//输入:abc或a b c scanf("%c%c%c",&a,&b,&c);//输入:abc(此时a b c就是错误的,因为空格等属于转义字符) printf("%c %c %c\n",a,b,c);
- scanf没有精度控制(即不能带n),例如scanf("%5.2f",&a)是错误的。但是可以有宽度控制(可以带m),例如scanf("2d",&a),带有m修饰符的整型数据输入可以不使用空格连续输入,系统会根据宽度自动截取相应的列数。(详细见格式修饰符第一点)
- scanf在输入时与printf一样,必须保证格式字符与后面输入项数据类型一致。但是scanf还要求个数一致,printf则没有
scanf函数虽然要求格式字符数据类型与个数必须与后面输入项一致,但是输入时,可以不输入相同类型,此时scanf输入相当于赋值表达式,会进行自动转换。scanf("%f",&a);//a是一个int类型,此时a=一个随机数,即输入的数据无法保存到变量a中。 printf("%d\n",1.34);//-687194767
float a; scanf("%f",&a);//输入123,此时相当于float a=123; printf("a=%f\n",a);//所以输出123.000000 int b; scanf("%4d",&b);//输入1.34A,此时相当于int b=1.34;(因为后面是char,所以必须连续输入,A考虑给后面的c) printf("b=%d\n",b);//所以输出1 char c; scanf("%c",&c);//这里虽然前面指定了m为4,但是由于b是int类型,所以只会截取到小数点之前,所以后面的c就是小数点 printf("c=%d\n",c);//输出c=46(小数点)
int a; char b; scanf("%d%c",&a,&b);//输入1.34a(因为a为int,所以int a=1.34只取小数点前,b为char要连续输入,所以b=. printf("a=%d\nb=%c\n",a,b);//输入:a=1 b=. float a; int b; char c; scanf("%f,%4d,%c",&a,&b,&c);//输入:123,1.34,A(float a=123,int b=1.34,char c=A) printf("a=%f\nb=%d\nc=%d\n",a,b,c);//a=123.000 b=1 c=0(系统在输入到b是取值1.34整数部分,后面还有个.34,由于没检测到,分隔符,所以认为非法输入
- scanf函数在遇到非法输入时会自动结束。例如输入int数据时默认空格分隔却以输入一个逗号作为分隔。
- 相邻的scanf可以不用回车直接空格连续输入,但是不推荐(循环连续输入也是)
int x,y,z=0; int x,y,z=0; scanf("%d",&x); 等同于 z++; z++; scanf("%d%d",&x,&y); scanf("%d",&y); //这两个程序在输入时,第一个输入:4 3(4会给x,3会给y)。第二个输入:4 3(4会给x,3会给y)。
- 在循环中连续输入char类型时,必须连续输入(scanf与getchar),除非有规定的分隔符。其它类型可选择输入一个回车在输入或者使用空格分隔再输入。
- 在以%s输入数据时,若输入的数据包含\0等转义字符,那么strlen和sizeof都会当作两个字符处理。
char str[20]; scanf("%s",str);//输入:123\0 printf("%d\t%d\n",sizeof(str),strlen(str));//20 5(由于输入的字符串必须使用字符数组保存,所以字符数组必须一开始就定义好长度,使用以下方法就可以测出实际占用内存长度) int i=0;//实际占用内存 while(*(str+i)!=0){ i++; } printf("i=%d\n",i+1);//i=6
- 整型数据使用十六进制与字符型输入时一般需要加分隔符,否则十六进制的a~f会与字符数据冲突。
- scanf函数和gets函数%s输入字符串后会自动加上\0,即会覆盖原来字符串的内容。
3.putchar()函数
格式:putchar(参数)【参数:字符变量、常量。整型变量、常量】
作用:向屏幕输出一个字符
-
putchar参数虽然可以是整型,但是却无法输出数值,所以整型应该保持在0~127的ASCLL码范围内以输出对应的字符。
-
多个putchar会连续输出(切记不会自动换行)
putchar(97); putchar(97); putchar('\n'); putchar(98); /* 输出:aa b */
-
putchar与getchar虽然只能输入输出单个字符,但是配合循环可以输入输出字符串(本质上还是单个字符的输入输出,只是调用了多次函数)
4.getchar()函数
格式:getchar(参数)
作用:输入一个字符
-
getchar()只能一个输入字符,如果输入的是数值,则取第一个数字。多个getchat输入一般采用循环的方式。
putchar(getchar());//输入97,输出9 for(int i=0;i<5;i++){ putchar(getchar());//getchar在循环中必须连续输入,例如此循环为5次数,输入hello必须连续输入hello。 //若是每输入一个回车一次,例如输入h 回车 h 回车 l 回车,输入到第三个就无法再属于了,因为用户 //输入三个字符还有两个回车,所以五个字符已经输入完成。回车不仅会立刻输出用户输入的字符,还占一 //个字符 }
-
多个getchar需要连续输入,输入完后Enter才输入完成。单个getchar也需要回车才能结束输入(因为空格等都属于转义字符,所以不连续输入会被当作字符处理,按回车之前输入的字符换存在键盘的缓冲器中
char a,b,c; a=getchar();//连续输入abc b=getchar(); c=getchar(); putchar(a);//连续输出abc putchar(b); putchar(c); putchar('\n');//换行回车
-
getchar输入的数据可以保存在变量中,也可以直接做表达式用于函数的参数等
char c=getchar(); printf("%c\n",getchar()); putchar(getchar());