:运算符、三大结构、文件操作)
文章目录1. 运算符1.1算术运算符1.2 关系运算符1.3 逻辑运算符1.4 位运算符1.5 赋值运算符1.6 其他运算符1.7 运算符优先级2. 三大结构2.1 选择结构2.1.1 条件运算符_?:2.2 循环结构2.2.1循环嵌套2.3 关键字break与continue3. 文件操作*. 其他限定符 - const限定符 - volatilevolatile指针多线程下的volatile断言 - assert声明外部变量_extern条件编译#ifndef、#endif和预定义#define、#undef关键字typedefC标准库和头文件关于表达式和语句的区别1. 运算符X元运算符根据运算符可操作的数据个数分为一元、二元、三元运算符也叫X目运算符识别真与假程序将0称为“假”将非0称为“真”运算结果真与假运算符运算的结果为真返回1为假则返回01.1算术运算符假设变量A的值为 10变量B的值为 20自增/自减运算符计算顺序前置形式先计算后赋值后置形式先赋值后计算q2*i;// 前缀形式i先进行自增计算计算的结果再和2相乘计算结果赋值给qq2*i;// 后缀形式i先和2相乘计算的结果赋值给q然后i进行自增计算// 自减运算符同理1.2 关系运算符关系运算符的优先级低于算术运算符高于赋值运算符1.3 逻辑运算符假设变量A的值为 1变量B的值为 0口诀与是有假为假或是有真为真1.4 位运算符在C语言的基本数据类型中char的位数最小——8位。可认为计算机以8位即1个字节为基本访问单元。小于一个字节的数据必须通过位操作来进行访问。按位与运算符|按位或运算符~按位非运算符按位取反^按位异或运算符相异为1 按位左移运算符各二进位全部左移若干位高位丢弃低位补0 按位右移运算符各二进位全部右移若干位对无符号数高位补0有符号数各编译器处理方法不一样有的补符号位算术右移有的补0逻辑右移应用位运算符对二进制数据进行按位操作假设变量A的值为 60十进制 0011 1100二进制变量B的值为 13十进制 0000 1101二进制按位与运算通常用来对某些位清 0或者仅保留某些位例如要把n的高 16 位清 0 保留低 16 位可以进行n 0X00FF运算0XFFFF在内存中的存储形式为0000 0000 0000 0000 1111 1111 1111 1111按位或运算可以用来将某些位置 1或者保留某些位例如要把n的高 16 位置 1保留低 16 位可以进行n | 0XFFFF0000运算0XFFFF0000在内存中的存储形式为1111 1111 1111 1111 0000 0000 0000 0000按位异或运算可以用来将某些二进制位反转例如要把n的高 16 位反转保留低 16 位可以进行n ^ 0XFFFF0000运算0XFFFF0000在内存中的存储形式为1111 1111 1111 1111 0000 0000 0000 0000左移 n 位相当于乘以 2 的 n 次方如果数据较小被丢弃的高位不包含 1那么左移 n 位相当于乘以 2 的 n 次方右移 n 位相当于除以 2 的 n 次方如果被丢弃的低位不包含 1那么右移 n 位相当于除以 2 的 n 次方但被移除的位中经常会包含 11.5 赋值运算符1.6 其他运算符1.7 运算符优先级运算符的优先级运算符的优先级决定算式运算的顺序更高的运算符拥有优先运算权以下由高至低列出运算符优先级2. 三大结构C语言三大语句结构顺序结构、选择结构和循环结构顺序结构C语言顺序结构就是让程序按照从头到尾的顺序依次执行每一条C语言代码不重复执行任何代码也不跳过任何代码2.1 选择结构选择结构让程序根据条件执行相应的行为if、ifelse、ifelse ifelse语句这些选择结构语句允许嵌套使用最后的else不是必要添加但是强烈建议每个选择结构都要带有else以防止出现不必要的异常当if条件语句运算结果为非0称为“真”表示条件成立否则为0称为“假”表示条件不成立C语言虽然没有限制if else能够处理的分支数量但当分支过多时用if else处理会不太方便而且容易出现if和else配对出错的情况这时就可以考虑使用switch case语句switch case语句首先计算“表达式”的值用该值自上往下与各个case语句的整型数值对比如果它们相等就执行冒号后面的语句和其后的所有case语句若不相等继续对比下一个如果直到对比最后一个整型数值都没有找到相等的值那么就执行default后的语句关键字breakbreak是C语言中的一个关键字专门用于跳出switch语句switch(表达式){case整型数值1:语句1;case整型数值2:语句2;......case整型数值n:语句 n;default:语句 n1;}// 示例switch(a){case1:printf(Monday\n);break;case2:printf(Tuesday\n);break;case3:printf(Wednesday\n);break;case4:printf(Thursday\n);break;case5:printf(Friday\n);break;case6:printf(Saturday\n);break;case7:printf(Sunday\n);break;default:printf(error\n);break;}2.1.1 条件运算符_?:条件运算符条件运算符是C语言中唯一的一个三目运算符其求值规则为如果表达式1的值为真则以表达式2 的值作为整个条件表达式的值否则以表达式3的值作为整个条件表达式的值// 语法格式表达式1?表达式2:表达式3// 以下语句同理max(ab)?a:b;if(ab){maxa;}else{maxb;}2.2 循环结构while语句计算“表达式”的值当值为真非0时 执行“语句块”执行完“语句块”再次计算表达式的值如果为真非0继续执行“语句块”重复步骤2和步骤3直到表达式的值为假0退出循环// 语法格式while(表达式){语句块}do-while语句与while循环的不同点为do-while先执行“语句块”然后再判断表达式是否为真非0如果为真则继续循环如果为假则终止循环// 语法格式do{语句块}while(表达式);for语句for(表达式1; 表达式2; 表达式3){语句块}先执行“表达式1”并只执行一次再执行“表达式2”如果它的值为真非0则执行“语句块”否则结束循环执行完“语句块”后再执行“表达式3”重复执行步骤 2和 3直到“表达式2”的值为假就结束循环表达式1、2、3都可以是空语句2.2.1循环嵌套在C语言中if-else、while、do-while、for都可以相互嵌套#includestdio.hintmain(){inti,j;for(i1;i4;i){//外层for循环for(j1;j4;j){//内层for循环printf(%-4d,i*j);}printf(\n);}return0;}2.3 关键字break与continuebreak直接跳出当前循环 /switchfor(inti1;i5;i){if(i3){break;// 直接结束整个循环}printf(i\r\n);}continue跳过本轮剩下代码直接进入下一轮循环只用在while、for循环中for(inti1;i5;i){if(i3){continue;// 跳过本次继续下一次}printf(i\r\n);}// 输出1 2 4 5⚠️在多层循环中一个break语句只向外跳一层#includestdio.hintmain(){inti1,j;while(1){// 外层循环j1;while(1){// 内层循环printf(%-4d,i*j);j;if(j4)break;//跳出内层循环}printf(\n);i;if(i4)break;// 跳出外层循环}return0;}3. 文件操作文件文件是数据源的一种最主要的作用是保存数据常见的 Word 文档、txt 文件、源文件等都是文件操作系统把硬件接口视作文件在操作系统中为了统一对各种硬件的操作简化接口操作系统对不同的硬件设备也都将其看成一个文件对它们的操作等同于对磁盘上普通文件的操作例如- 通常把显示器称为标准输出文件printf就是向这个文件输出数据- 通常把键盘称为标准输入文件scanf就是从这个文件读取数据操作文件的正确流程打开文件 -- 读写文件 -- 关闭文件打开文件即获取文件的相关信息如文件名、文件状态、读写位置等这些信息会被保存到一个FILE类型的结构体变量中关闭文件就是断开与文件之间的联系释放结构体变量同时禁止再对该文件进行操作文件流所有的文件磁盘数据都要载入到内存才能处理所有的数据必须写入文件磁盘才不会丢失数据在文件磁盘和内存之间传递的过程叫做文件流数据流(Data Stream)把数据在数据源磁盘和程序内存之间传递的过程分为输入流和输出流输入流(Input Stream) 数据从数据源磁盘复制到程序内存的过程输出流(Output Stream)数据从程序内存复制到数据源磁盘的过程数据源数据的源头如文件、数据库、网络、键盘等数据传递到内存在C语言中即保存到变量中如整数、字符串、数组、缓冲区等更多文件操作内容C语言文件操作详解*. 其他限定符 -const限定只读变量被const定义的变量只允许被读不可被写即把变量视作常量constintMONTHS12;// MONTHS被定义为静态变量变量类型为int值为12,它不可被更改#define和const都可以把变量视作常量前者是一种宏定义后者是一种变量限定const的优势是它明确指定了变量的数据类型其次被const定义的变量可将其限制在特定的作用域内再者const可用于更复杂的数据类型如数组和结构体等限定符 -volatilevolatile关键字和const对应是一种类型修饰符用来修饰变量。当要求使用 volatile 声明的变量的值时系统总是从它所在的内存读取数据。如下代码volatile指明 i 是随时可能发生变化的变量每次使用它的时候必须从 i的地址中读取因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中此称为不对该变量代码进行优化。反之代码经过优化的做法是由于编译器发现两次从 i读数据的代码之间的代码没有对 i 进行过操作它会自动把上次读的数据放在 b 中。而不是重新从 i 里面读。这样如果 i是一个寄存器变量或者表示一个端口数据就容易出错所以volatile保证了对特殊地址的稳定访问。volatileinti10;intai;...// 其他代码并未明确告诉编译器对 i 进行过操作intbi;volatile用的最多的地方是多线程并发访问共享变量时一个线程改变了变量的值怎样让改变后的值对其它线程保持可见。这种情况下volatile用在如下的几个地方中断服务程序中修改的供其它程序检测的变量需要加volatile多任务环境下各任务间共享的标志应该加volatile存储器映射的硬件寄存器通常也要加volatile说明因为每次对它的读写都可能有不同意义volatile指针const有常量指针和指针常量的说法volatile也有相应的概念表示由该指针指向的对象、数据是 const 或 volatile 的constchar*cpch;volatilechar*vpch;注意可以把一个非volatile int赋给volatile int但是不能把非volatile对象赋给一个volatile对象。除了基本类型外对用户定义类型也可以用volatile类型进行修饰。C中一个有volatile标识符的类只能访问它接口的子集一个由类的实现者控制的子集。用户只能用const_cast来获得对类型接口的完全访问。此外volatile向const一样会从类传递到它的成员。多线程下的volatile当两个线程都要用到某一个变量且该变量的值会被改变时应使用volatile声明其作用是防止编译器的优化工作将变量从内存装入 CPU 寄存器中。如果变量被装入寄存器那么两个线程有可能一个使用内存中的变量一个使用寄存器中的变量这会造成程序的错误执行。volatile的作用是让编译器每次操作该变量时一定要从内存中真正取出而不是使用已经存在寄存器中的值。// volatile变量定义volatileBOOL bStopFALSE;// 在一个线程中while(!bStop){...}bStopFALSE;return;// 在另一个线程中bStopTRUE;while(bStop);//等待上面的线程终止如果bStop不使用volatile申明那么这个循环将是一个死循环因为bStop已经读取到了寄存器中寄存器中bStop的值永远不会变成FALSE加上volatile程序在执行时每次均从内存中读出bStop的值就不会死循环了。断言 -assertassert()函数包含在头文件assert.h中它可用于在 C 程序中添加输入参数诊断。函数定义voidassert(intexpression);其中expression可以是一个变量或任何 C 表达式。如果expression为 TRUEassert()不执行任何动作。如果expression为FALSEassert()会在标准错误 stderr 上显示错误消息并中止程序执行。例程#includeassert.h#includestdio.hintmain(){inta;charstr[50];printf(请输入一个整数值 );scanf(%d,a);assert(a10);//若变量a不满足条件则终止程序执行并报错printf(输入的整数是 %d\n,a);printf(请输入字符串 );scanf(%s,str);assert(str!NULL);printf(输入的字符串是 %s\n,str);return(0);}声明外部变量_extern扩展全局变量的作用域全局变量的作用域是同一文件内要在另一个文件内使用同一个全局变量就需要在另一个 文件内使用关键字extern声明该全局变量已在别的文件定义过在file1中定义全局变量inti0;// 在变量定义时赋初始值在file2中声明extern全局变量externinti;// 不能再赋值条件编译#ifndef、#endif和预定义#define、#undef预定义又叫宏定义在运行程序前所有被#define定义的目标的替换工作均已完成故称预定义预定义可以定义很多数据类型的变量、算式、常量甚至函数使用大写按C语言的传统被#define定义的目标习惯使用大写目的是提高代码阅读性#undef用于“取消”已定义的#define指令符号常量被#define定义的常量符号常量的命名规则与变量命名规则同理可使用大小写字母、数字和下划线字符首字符不能为数字#defineTAXRATE0.015// 用TAXRATE 宏替代 0.015这种常量被称为符号常量#defineMAX(x,y)(((x)(y))?(x):(y))// 求得两个数的最大值#defineMIN(x,y)(((x)(y))?(x):(y))// 求得两个数的最小值#undefTAXRATE// 取消TAXRATE的预定义条件编译#ifndef主要用于防止一个预定义被重复定义或头文件被重复包含。其编译工作也在程序运行之前完成。#ifndefCOMDEF_H// 若已存在宏定义COMDEF_H#defineCOMDEF_H// 包含的头文件、执行的代码等#else// 否则...#endif宏定义的其他常用方式得到指定地址上的一个字节或字#defineMEM_B(x)(*((byte*)(x)))#defineMEM_W(x)(*((word*)(x)))得到一个字的高位和低位字节#defineWORD_LO(xxx)((byte)((word)(xxx)255))#defineWORD_HI(xxx)((byte)((word)(xxx)8))返回一个比X大的最接近的8的倍数#defineRND8(x)((((x)7)/8)*8)将一个字母转换为大写#defineUPCASE(c)(((c)a(c)z)?((c)-0x20):(c))判断字符是不是10进制的数字#defineDECCHK(c)((c)0(c)9)判断字符是不是16进制的数字#defineHEXCHK(c)(((c)0(c)9)||((c)A(c)F)||((c)a(c)f))防止数据溢出#defineINC_SAT(val)(val((val)1(val))?(val)1:(val))返回数组元素的个数#defineARR_SIZE(a)(sizeof((a))/sizeof((a[0])))关键字typedeftypedef为数据类型或结构体起一个新的别名语法typedef oldName newName;// 给int取别名typedefintINTEGER;INTEGER a,b;// 给结构体取别名typedefstructstu{charname[20];intage;charsex;}STU;// 以下两种定义结构体变量的方式都可以STU body1,body2;structstubody1,body2;常用的数据类型别名如下目的是防止由于各种平台和编译器的不同而产生的类型字节数差异方便移植。typedefunsignedcharboolean;/* Boolean value type.1 bit value*/typedefunsignedlongintuint32;/* Unsigned 32 bit value */typedefunsignedshortuint16;/* Unsigned 16 bit value */typedefunsignedcharuint8;/* Unsigned 8 bit value */typedefsignedlongintint32;/* Signed 32 bit value */typedefsignedshortint16;/* Signed 16 bit value */typedefsignedcharint8;/* Signed 8 bit value */C标准库和头文件C语言的三套标准C89、C99和C11C标准库 十五个头文件标准C语言ANSI C共定义了15 个头文件组成C标准库所有的编译器都必须支持stdint.h和inttypes.h支持代码可移植在不同的操作系统中对于同一数据类型关键字可能有不同的定义在代码中包含上述头文件后代码会根据当前系统定义关键字的功能inttypes.h File Reference如int32_t表示32位的有符号整数类型在32位操作系统中头文件stdint.h会把int32_t处理为int的别名而在16位操作系统中把int32_t处理为long的别名;limits.h该标准库头文件决定了各变量类型的各种属性定义在该头文件中的宏限制了各种变量类型的值这些限制指定了变量不能存储任何超出指定的限制值例如一个无符号可以存储的最大值是 255C 标准库 - limits.hstring.h专门用来处理字符串的头文件它包含了很多字符串处理函数关于表达式和语句的区别表达式expression结果为一个值的式子444q44q4// 以上都是表达式intport/* 不是表达式没有值 */语句statement语句是C程序的基本结构一条语句相当于一条完整的计算机指令在表达式后加上;表达式就成了语句;// 空语句8;88;q44;// 以上都是语句