c语言基础
第一个C语言程序
#include <stdio.h> int main() { printf("hello world!\n"); return 0; }
#include 预处理命令 stdio.h 标准输入输出头文件 printf 输出括号内的字符串,字符串要用双引号括起来 \n 换行符 return 0 函数的返回值 每个语句结尾要加分号;
GCC编译器
gcc 可选项 源文件
-
gcc编译流程
可选项 | 对应的语言 |
---|---|
-c | 只编译不链接,生成目标文件 ".o" |
-S | 只编译不汇编,生成汇编代码 |
-E | 只进行预编译,不做其他处理 |
-g | 在可执行程序中包含标准调试信息 |
-o file | 把输出文件输出到file里 |
-v | 打印出编译器内部编译各过程的命令行信息和编译器的版本 |
【1】预处理阶段
去掉注释,加载头文件,代替宏定义,条件编译
条件编译 需要文件:.c文件 生成产物:预处理文件(以.i结尾)
gcc -E [源文件] -o [目标文件]
实例:gcc -E hello.c -o hello.i
后缀名为”.i”的文件是经过预处理后的C原始程序。
【2】编译阶段
编译阶段的主要工作是把我们的源代码生成相应的汇编代码的过程。这个阶段花费的时间会比较长。它需要对我们的C语言进行语法和语义的分析,如果有语法错误,报错,并结束编译过程;如果没有语法错误。此外,还需要优化我们的代码把C的源程序转变为汇编代码。需要文件:.i文件 生成产物:汇编文件(以.s结尾)。
gcc -S [源文件] -o [目标文件]
实例:gcc -S hello.i -o hello.s
后缀名为”.s”的文件是汇编语言原始程序。
【3】汇编阶段
首先我们应该知道汇编代码(汇编指令)并不是机器能够执行的语言。我们还必须把汇编语言翻译成计算机能识别的机器语言,这个翻译的过程是在汇编阶段完成的。所以在这个阶段把汇编源文件通过汇编器生成目标文件(二进制机器语言)。
gcc -c [源文件] -o [目标文件]
实例:gcc -c hello.s -o hello.o
C 语言代码经过编译以后,并没有生成最终的可执行文件(.exe 文件),而是生成了一种叫做目标文件(Object File)的中间文件(或者说临时文件)。目标文件也是二进制形式的,它和可执行文件的格式是一样的。对于 Visual C++,目标文件的后缀是.obj;对于 GCC,目标文件的后缀是.o。
【4】链接阶段
把目标文件执行所依赖的所有二进制的其他目标文件及C的库文件都整合成一个可执行文件的过程 需要文件:.o文件及各种动态库或静态库 生成产物:可执行程序。
gcc [源文件] -o [目标文件]
实例:gcc hello.o -o hello
编译只是将我们自己写的代码变成了二进制形式,它还需要和系统组件(比如标准库、动态链接库等)
结合起来, 链接(Link)其实就是一个“打包”的过程,它将所有二进制形式的目标文件和系统组件组合成一个可执行文件。
linux@ubuntu:~/test_c$ gcc test01.c linux@ubuntu:~/test_c$ ls a.out test01.c linux@ubuntu:~/test_c$ ./a.out hello world! linux@ubuntu:~/test_c$ gcc test01.c -o test01 linux@ubuntu:~/test_c$ ls a.out test01 test01.c linux@ubuntu:~/test_c$ ./test01 hello world! linux@ubuntu:~/test_c$ gcc -E test01.c -o test01.i linux@ubuntu:~/test_c$ ls a.out test01 test01.c test01.i linux@ubuntu:~/test_c$ gcc -S test01.i -o test01.s linux@ubuntu:~/test_c$ ls a.out test01 test01.c test01.i test01.s linux@ubuntu:~/test_c$ gcc -c test01.s -o test01.o linux@ubuntu:~/test_c$ ls a.out test01 test01.c test01.i test01.o test01.s linux@ubuntu:~/test_c$ gcc test01.o -o hello linux@ubuntu:~/test_c$ ls a.out hello test01 test01.c test01.i test01.o test01.s linux@ubuntu:~/test_c$ ./hello hello world!
printf打印不同颜色
在嵌入式开发,服务器开发中,经常用到printf,在项目比较大,或者打印信息比较多时,可以通过打印的字符串的颜色的不同来凸显重要信息。
格式如下:
printf("\033[字背景颜色;字体颜色;控制码m 字符串 \033[0m");
颜色代码:
字背景颜色范围: 40—47 | 字颜色: 30—37 |
---|---|
40: 黑 | 30: 黑 |
41: 红 | 31: 红 |
42: 绿 | 32: 绿 |
43: 黄 | 33: 黄 |
44: 蓝 | 34: 蓝 |
45: 紫 | 35: 紫 |
46: 深绿 | 36: 深绿 |
47: 白色 | 37: 白色 |
ANSI控制码:
\033[0m | 关闭所有属性 |
---|---|
\033[1m | 设置高亮度 |
\033[4m | 下划线 |
\033[5m | 闪烁 |
\033[7m | 反显 |
\033[8m | 消隐 |
\033[30m -- \033[37m | 设置前景色 |
\033[40m -- \033[47m | 设置背景色 |
\033[nA | 光标上移n行 |
\03[nB | 光标下移n行 |
\033[nC | 光标右移n行 |
\033[nD | 光标左移n行 |
\033[y;xH | 设置光标位置 |
\033[2J | 清屏 |
\033[K | 清除从光标到行尾的内容 |
\033[s | 保存光标位置 |
\033[u | 恢复光标位置 |
\033[?25l | 隐藏光标 |
\33[?25h | 显示光标 |
vim命令模式下,gg=G:整理代码
注释
注释用于描述特定的命令、函数或程序,增强程序的可读性,是编写程序代码的人为了方便理解代码所写的文本,被注释的文本不会被执行(因为在预处理阶段被删除)。
-
普通注释
【1】行注释:使用 //, 注释一行 【2】块注释:使用/* */, 注释一段,多行注释用 /* 开始,用 */ 结束(标准C语言)
-
使用条件编译快速注释
当需要注释的代码量较多时,如果使用块注释(/* */)则会出现无法配对等情况 此时可以使用以下方法来快速注释一段代码:
#if 0 待注释代码…… #endif
当需要取消这段注释时,只需将0改成1即可
#if 1 待注释代码…… #endif
C语言编码规范
-
命名规范
【1】在所有命名中,都应使用标准的英文单词或缩写。
【2】所有命名都应遵循达意原则,即名称应含义清晰、明确。
【3】所有命名都不易过长,应控制在规定的最大长度以内,一般不超过32个字节。
-
编码规范
【1】在一行代码内只写一条语句;
【2】在嵌套的函数块中使用一个TAB缩进;
【3】每行长度不应超过80个字符;
【4】一个函数建议不要超过200行代码;
【5】程序中结束符号;(分号)前面不要加空格;
【6】为程序添加适当的注释;
-
代码要求
【1】代码格式清楚、层次分明;
【2】代码易于理解、可读性强;
【3】代码具有健壮性,且没有错误;
标识符与关键字
字符集
-
英文字母:大小写26个,共52个;
-
阿拉伯数字:0~9;
-
下划线(_)与冒号(:);
-
特殊符号。
运算符
-
算术运算符:+、-、*、\、%、++、--
-
关系运算符:<、>、>=、<=、==、!=
-
逻辑运算符:&&、|| 、!
-
位运算符:& | ~ ^ >> <<
-
条件运算符:? :
-
分隔符: () [] {} . , ;
标识符
用于标识变量名、符号常量名、函数名、类型名、文件名等的有效字符序列。
标识符的命名规则
-
标识符只能由字母、数字和下划线三种字符组成,且第一个字符必须为字母或下划线;
-
C 语言中的标识符大小写敏感;
-
用户自定义的标识符不能与关键字同名。
关键字
基本数据类型
void:声明函数无返回值或无参数,声明无类型指针,显示丢弃运算结果。 char:字符型类型数据,属于整型数据的一种。 int:整型数据,表示范围通常为编译器指定的内存字节长。 float:单精度浮点型数据,属于浮点数据的一种。 double:双精度浮点型数据,属于浮点数据的一种。 //_Bool:布尔型(C99标准新增) //_Complex:复数的基本类型(C99标准新增) //_Imaginary:虚数,与复数基本类型相似,没有实部的纯虚数(C99标准新增) //_Generic:提供重载的接口入口(C11标准新增)
类型修饰关键字
short:修饰int,短整型数据,可省略被修饰的int。 long:修饰int,长整型数据,可省略被修饰的int。 // long long:修饰int,超长整型数据,可省略被修饰的int。(C99标准新增) signed:修饰整型数据,有符号数据类型。(C89标准新增) unsigned:修饰整型数据,无符号数据类型。 // restrict:用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式。(C99标准新增)
复杂类型关键字
struct:结构体声明。 union:联合体声明。 enum:枚举声明。(C89标准新增) typedef:声明类型别名。 sizeof:得到特定类型或特定类型变量的大小。 // inline:内联函数用于取代宏定义,会在任何调用它的地方展开。(C99标准新增)
存储级别关键字
auto:指定为自动变量,由编译器自动分配及释放。通常在栈上分配。与static相反。当变量未指定时默认为auto。 static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部。 register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数。 extern:指定对应变量为外部变量,即标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。 const:指定变量不可被当前线程改变(但有可能被系统或其他线程改变)。(C89标准新增) volatile:指定变量的值有可能会被系统或其他线程改变,强制编译器每次从内存中取得该变量的值,阻止编译器把该变量优化成寄存器变量。(C89标准新增)
流程控制关键字
-
跳转结构
return:用在函数体中,返回特定值(如果是void类型,则不返回函数值)。 continue:结束当前循环,开始下一轮循环。 break:跳出当前循环或switch结构。 goto:无条件跳转语句。
-
分支结构
if:条件语句,后面不需要放分号。 else:条件语句否定分支(必须与if连用)。 switch:开关语句(多重分支语句)。 case:开关语句中的分支标记,与switch连用。 default:开关语句中的“其他”分支,可选。 for:循环 while:循环
变量与常量
在程序的指示下,计算机可以做很多事儿:数值计算、名字排序、计算彗星轨道、准备邮寄列表等。要完成这些任务,程序需要使用数据,即承载信息的数字与字符。有些数据可以在程序使用前预先设定并在整个运行过程中没有变化,这个称为常量。另外的数据在程序运行过程中可能变化或被赋值,这称为变量。
变量
所谓变量是指在程序运行过程中其值可以改变的量。使用变量时必须“先定义,后使用”。
变量的定义
在程序中,用到的所有变量必须有一个名字作为标识,变量名由用户定义,它必须符合标识符的命名规则。
编译系统将大写字母和小写字母认为是两个不同的字符。 在选择变量名和其它标识符时,应注意做到"见名知意",即选有含意的英文单词 (或其缩写)作标识符。
数据类型 变量名称;
变量的初始化
在C语言中,未初始化的局部变量为乱码,因此使用之前需要事先给值
定义时初始化变量
int num=666; =:赋值号
定义后初始化变量
int num; num=666;
变量的实质
一个变量实质上代表了内存中某个存储单元。在程序中,变量a就是指用a命名的某个存储单元,用户对变量a进行操作就是对该存储单元进行操作;给变量a赋值,实质上就是把数据存如该变量所代表的存储单元中。
变量的地址
变量在内存中总占用几个连续的字节,开始字节的地址,就是变量的地址。
练习:交换两个变量的值
//中间变量 #include <stdio.h> int main() { int a=66; int b=88; int temp; temp=a; a=b; b=temp; printf("a=%d,b=%d\n",a,b); return 0; }
常量
在程序执行过程中,其值不被改变的量。常量主要分为两类:
直接常量:直接引用的数字等;
字符常量 ‘A’ , ‘a’
整型常量 10 100 0b1101 0664 0xaf
实型常量 3.14 5.69
字符串常量 "hello world","100"
符号常量:使用标识符来代替一个数字(常见的:宏定义常量 和 常变量)
宏定义
#define 也是C语言预处理命令的一种,被称为宏定义指令。
所谓宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。
每行#define都由3部分组成。
#define 宏名 替换体 //第一部分是#define指令本身。 //第二部分是选定的缩写,也称为宏。有些宏代表值,这些宏被称为类对象宏(object-like macro);C语言还有类函数宏(function-like macro)。宏的名字中不允许有空格,而且必须遵循C变量的命名规则。 //第三部分称为替换列表或替换体。一旦预处理器在程序中找到宏的实例后,就会用替换体代替该宏(也有例外)。从宏变成最终替换文本的过程称为宏展开(macro expansion)。
类对象宏(object-like macro不带参宏)
#define 宏名 宏值
#include <stdio.h> #define NUM 10 #define SUM "hello" #define A 'a' int main(int argc, const char *argv[]) { printf("%d\n",NUM); //%d输出整型数据 printf("%s\n",SUM); //%s输出字符串 printf("%c\n",A); //%c输出字符 return 0; }
类函数宏(带参数宏)
#define 宏名(参数列表) 宏值
#include <stdio.h> #define PI 3 #define S(r) PI*r*r int main(int argc, const char *argv[]) { int r=5; printf("S(r)=%d\n",S(r)); return 0; }
使用宏定义的优点:
-
给数值赋予一定含义,增强代码可读性
-
减少代码编写量
-
可以“一改全改”
//输入程序,对比以下两个宏定义的不同 #include <stdio.h> #define FUN1(a,b) a*b #define FUN2(a,b) (a)*(b) int main() { int a=2; int b=3; printf("%d\n",FUN1(a+b,b+a)); printf("%d\n",FUN2(a+b,b+a)); return 0; }
FUN1 a+b*b+a FUN2 (a+b)*(b+a)
常变量
变量值不可改变的量,使用const修饰
const int a = 10; // 定义一个常变量 a = 9; // 报错,a为const修饰不可改变。
#include <stdio.h> int main() { int a=10; const int b=20; printf("a=%d,b=%d\n",a,b); a=66; //b=88; printf("a=%d,b=%d\n",a,b); return 0; }
注意:
const修饰后的变量会变成只读,因此无法再次赋值。因此初始化常变量需要在定义时直接赋值。
常变量与宏定义常量的区别:
宏定义常量是在预处理阶段,使用宏名来代替宏值。而常变量是在程序运行时,程序在内存分配的一个变量,只不过变量不允许再次赋值。
数据类型
整型
整型类型包括短整型(short int)、基本整型(int)、长整型(long int),它们又被分为有符号(signed)和无符号(unsigned)两种。
-
基本型:类型说明符为int:值必须是整数,可以是正的,负的或者是0;其取值范围依赖于计算机系统。
-
短整型:类型说明符为short int或short,用于仅需小数值的场合以节省空间。
-
长整型:类型说明符为long int或long,用于使用大数值的场合。
-
无符号型:类型说明符为unsigned。无符号型又可与上述三种类型匹配而构成,只用于非负值的场合
-
无符号基本型:类型说明符为unsigned int或unsigned。
-
无符号短整型:类型说明符为unsigned short。
-
无符号长整型:类型说明符为unsigned long。
-
整型长度
实际情况也确实如此, C 语言并没有严格规定 short、 int、 long 的长度,只做了宽泛的限制:
-
short 至少占用 2 个字节。
-
int 建议为一个机器字长。 32 位环境下机器字长为 4 字节, 64 位环境下机器字长为 8 字节。
-
short 的长度不能大于 int, long 的长度不能小于 int。
总结起来,它们的长度(所占字节数)关系为:
2 ≤ short ≤ int ≤ long
sizeof运算符
获取某个数据类型或变量的长度可以使用 sizeof 操作符,以字节为单位来计数。
对于sizeof(),其形式类似于函数,但本质是C语言的一个运算符,且对 sizeof() 的处理都是在编译阶段进行。
#include <stdio.h> int main() { printf("short=%d\n",sizeof(short)); printf("int=%d\n",sizeof(int)); printf("long int=%d\n",sizeof(long int)); printf("unsigned int=%d\n",sizeof(unsigned int)); printf("unsigned long=%d\n",sizeof(unsigned long int)); return 0; }
#include <stdio.h> int main() { int a=0; scanf("%d",&a); printf("a=%d\n",a); return 0; }
整数型常量
在C语言中,整常数有二进制、八进制、十六进制和十进制四种。在程序中是根据前缀来区分各种进制数的
[1] 十进制
十进制整常数没有前缀。其数码为0~9,只要常数中不含小数点和指数的数编译器都会当作整数。
合法的表达方式:237、-568、65535、1627;
非法的表达方式:023 (不能有前导0)、23D (含有非十进制数码)。
[2] 八进制
八进制整常数必须以0开头,即以0作为八进制数的前缀。数码取值为0~7。
合法的表达方式:015(十进制为13)、0101(十进制为65)、0177777(十进制为65535);
非法的表达方式:256(无前缀0)、03A2(包含了非八进制数码)。
[3] 十六进制
十六进制整常数的前缀为0X或0x。其数码取值为0~9,A~F或a~f。
合法的表达方式:0X2A(十进制为42)、0XA0 (十进制为160)、0XFFFF (十进制为65535)
非法的表达方式:5A (无前缀0X)、0X3H (含有非十六进制数码)。
[4] 二进制
二进制由 0 和 1 两个数字组成,使用时必须以 0b 或 0B(不区分大小写)开头
合法的表达方式:0b101(换算成十进制5)、0b110010(换算成十进制50)、0B100001(换算成);
非法的表达方式:101010(无前缀0B,相当于十进制)0B410(含有非二进制数码)。
注意:
标准的 C 语言并不支持上面的二进制写法,只是有些编译器自己进行了扩展,才支持二进制数字。 换句话说,并不是所有的编译器都支持二进制数字,只有一部分编译器支持,并且跟编译器的版本有关系。
整数的显示方法
显示十进制整数
%hd、 %d、 %ld 以十进制、有符号的形式输出 short、 int、 long 类型的整数 %hu、 %u、 %lu 以十进制、无符号的形式输出 short、 int、 long 类型的整数
显示八进制整数
%ho、 %o、 %lo 以八进制、不带前缀、无符号的形式输出 short、 int、 long 类型的整数 %#ho、 %#o、 %#lo 以八进制、带前缀、无符号的形式输出 short、 int、 long 类型的整数
显示十六进制整数
以十六进制、不带前缀、无符号的形式输出 short、 int、 long 类型的整数。如果 x 小写,那么输出的十六进制数字也小写;如果 X 大写,那么输出的十六进制数字也大写。
%hx、 %x、 %lx %hX、 %X、 %lX
以十六进制、带前缀、无符号的形式输出 short、 int、 long 类型的整数。如果 x 小写,那么输出的十六进制数字和前缀都小写;如果 X 大写,那么输出的十六进制数字和前缀都大写。
%#hx、 %#x、 %#lx %#hX、 %#X、 %#lX
实型(浮点型)
单精度(float型)/ 双精度(double型)/ 长双精度型(long double)
浮点数的表现形式
[1] 小数形式
由数码0~ 9和小数点组成。例如 0.0、 75.0、 4.023、 0.27、 -937.198 等都是合法的小数
[2] 指数形式
例如 7.25×(10^2)、 0.0368×(10^5)、 100.22×(10^-2)、 -27.36×(10^-3) 等。
任何小数都可以用指数形式来表示。但是在书写时, C 语言中的指数形式和数学中的指数形式有所差异。
C 语言中小数的指数形式为:
aEn 或 aen
a 为尾数部分,是一个十进制数;n 为指数部分,是一个十进制整数;E 或 e 是固定的字符,用于分割尾数部分和指数部分。整个表达式等价于 a×(10^n)。例如:
2.1E5 = 2.1×(10^5),其中 2.1 是尾数, 5 是指数。 3.7E-2 = 3.7×(10^-2)其中 3.7 是尾数, -2 是指数。 0.5E7 = 0.5×(10^7),其中 0.5 是尾数, 7 是指数。
浮点数的输出格式
小数也可以使用 printf 函数输出,包括十进制形式和指数形式,它们对应的格式控制符分别是:
%f:输出十进制计数法的float和double数字; %e:输出指数计数法的float和double数字; %lf、%le:输出double类型的数字; %Lf、%Le:输出long double类型的数字;
#include <stdio.h> int main() { float a=0.666; double b=123.0; long double c=0.7623e-2; printf("a=%e,a=%f\n" "b=%e,b=%f,b=%le,b=%lf\n" "c=%Lf,c=%Le\n",a,a,b,b,b,b,c,c); return 0; }
字符型(char)
字符并不是任意写一个字符,程序都能识别。例如圆周率π在程序中是不能被识别的,只能使用系统的字符集中的字符,目前大部分系统采用美国信息交换标准代码ASCII码(American Standard Code for Information Interchange)字符集。基本ASCII码标准定义了128个字符,用七位二进制来编码,包括英文大写字母26个、小写字母26个、数字符号0~9十个,还有一些专用符号(如“:”、“!”、“%”)及控制符号(如换行、换页、回车等)。
值 | 符号 | 值 | 符号 | 值 | 符号 |
---|---|---|---|---|---|
0 | 空字符 | 44 | , | 91 | [ |
32 | 空格 | 45 | - | 92 | \ |
33 | ! | 46 | . | 93 | ] |
34 | " | 47 | / | 94 | ^ |
35 | # | 48 ~ 57 | 0 ~ 9 | 95 | - |
36 | $ | 58 | : | 96 | ` |
37 | % | 59 | ; | 97 ~ 122 | a ~ z |
38 | & | 60 | < | 123 | { |
39 | ' | 61 | = | 124 | | |
40 | ( | 62 | > | 125 | } |
41 | ) | 63 | ? | 126 | ~ |
42 | * | 64 | @ | 127 | DEL(Delete键) |
43 | + | 65 ~ 90 | A ~ Z |
字符变量
字符变量使用类型字符char定义的变量。char是英文character(字符)的缩写。字符变量实质上是的整型变量的一种,一般占用一个字节(8bit),由于它常用来存储字符。所以称为字符变量。当它用于存储字符常量时,实际上是将该字符的ASCII码值存储到内存单元。例如,char c = ‘?’
定义一个字符变量c并使初值为字符’?’。’?’的ASCII代码是63,系统把整数63赋给变量c
在输出字符变量的值时,可以选择以十进制整数形式输出,或以字符形式输出。如:
#include <stdio.h> int main() { char a,b; int c,d; a=c=65; b=d='A'; printf("char a=%c,int c=%c\n",a,c); printf("char b=%d,int d=%d\n",b,d); return 0; }
运算符和表达式
C语言中用于告诉程序执行特殊算术或逻辑操作的符号称为运算符,运算的对象称为操作数。
用运算符和括号将操作数连接起来的符合C语言语法规则的句子称为表达式。
运算分类
【1】根据结合操作数的数目分类:(一元/二元/三元)
单目运算符:即操作数只有1个的运算符 i++,++i
双目运算符:即操作数有2个的运算符 +-*/
三目运算符:即操作数有3个的运算符,只有一个( ?: )
【2】根据运算符的用途分类:
赋值运算符:如=及其扩展运算符
逻辑运算符:如&&(与)、||(或)、!(非)
算数运算符:如+ - * / %等
关系运算符:如> < >= <= == !=等
位运算符:如<< >>等
条件运算符:只有一个: ?:
逗号运算符:只有一个 , 用于分隔
运算结合方向
运算符有两种结合顺序:自左至右、自右至左
自左至右(左结合性):表示运算符的操作数是从左向右(先左再右)与运算符结合的,如加法+
例:3 + 5,即3加上5,先取3,再取+,再取5
自右至左(右结合性):表示运算符的操作数是从右向左(先右再左)与运算符结合的,如赋值=
例:a = 3,即先取数3,再给a赋值
运算符优先级
C语言中运算符有优先级,从高到低分为15级(不同书籍划分方式不同,级数不同,这里采用百度百科划分方式),1级优先级最高,15级最低。
说明:
同一优先级的运算符,结合次序由结合方向所决定。
例如:对于表达式”x – y + z”,由于”-”和”+”都是同一级别的优先级,而它们的结合方向是左结合性,因此先计算”x-y”
简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
算数运算符
四则运算符和求模运算符
符号及含义:+(加) -(减) *(乘) /(除) %(取余)
数目:双目运算符
结合性:自左至右
优先级:+和-:4级。*和/和%:3级
使用方法:表达式 运算符 表达式。如:3+5 a-b等
注意:
① C语言中,若相除2个数都是整数,则计算/时只取商,余数部分被舍去。
② %的操作数必须是整数
#include <stdio.h> int main() { float a=5.0; int b=2; int c=5; printf("%.2f\n",a/b); //%.2f:输出小数点后两位 printf("%d\n",c/b); //printf("%d\n",a%b); 编译不通过 printf("%d\n",c%b); return 0; }
正运算符和负运算符
符号及含义:+(正数) -(负数)
数目:单目运算符
结合性:自右至左
优先级:2级
使用方法:+ 表达式 或 - 表达式。如:
int a = 3; printf("%d\n", -a); // 对a取负数,会输出-3
自增运算符和自减运算符
符号及含义:++(自增1) --(自减1)
数目:单目运算符
结合性:自左至右 或 自右至左(取决于运算符位置)
优先级:2级
使用方法:
自增;变量++ 或 ++变量。如a++ 或 ++a
自减:变量-- 或 --变量。如b-- 或 --b
注意:
① 自增或自减运算符仅用于变量,不能用于常量或表达式
② 注意++/--运算符与+/-(正数/负数运算符)是同等优先级。当这两个运算符一起使用时,是右结合性。
即--a++ <---等价于---> --(a++);
③ 自增或自减运算符可用在操作数之前,也可以放在其后,这两种用法稍有区别:
-
运算符在操作数前时:
C语言在引用操作数之前那就先执行加1或减1
例如:j = ++i;其执行过程是,先将变量i+1,再将计算结果赋给j。
-
运算符在操作数后时:
C语言先引用操作数的值,然后再进行加1或减1,
例如:j= i--;其执行过程是,先将变量i的值赋值给j;再执行将变量i-1。
关系运算符
符号及含义:>(大于) <(小于) >=(大于等于) <=(小于等于) ==(判等) !=(不等)
数目:双目运算符
结合性:自左至右
优先级:> < >= <=:6级。==和!=:7级
使用方法:表达式 运算符 表达式。如3<5,a==7等
注意:
① 关系运算符的操作数可以是变量、常量和表达式
② 关系表达式的的值是一个逻辑值:关系成立,即为真,结果为1;关系不成立,即为假,结果为0
③ 注意区分判断两个表达式相等的运算符是==,与=(赋值运算符)
逻辑真值和逻辑假值在c里是如何表达的?
0表示逻辑假,如0、0.0、\0、NULL
非0表示逻辑真,而且非零不一定是整数,可以是任何类型
逻辑运算符
逻辑运算符用于,对包含关系运算符的表达式进行逻辑上的合并或取非。
符号及含义:&& (逻辑与) ||(逻辑或) !(逻辑非)
数目:! 为单目运算符,&& 和 || 为双目运算符
结合性:! 为自右至左,&&和 || 为自左至右
优先级:!:2级、&&:11级、||:12级
使用方法:
&&和||:表达式 运算符 表达式。
如:a && b、a || b
!:!表达式。如 !a
注意:
① 逻辑与:当且仅当两个表达式都为真时,则计算结果为真。否则为假
② 逻辑或:当且仅当两个表达式都为假时,则计算结果为假。否则为真
③ 逻辑非:当原表达式为真时,计算结果为假;当原表达式为假时,计算结果为真
④ 使用逻辑运算符的表达式结果为真或假;
条件运算符
符号及含义: ?: (判断?前表达式是否成立,若成立取:前表达式,否则取:后表达式)
数目:三目运算符(C语言中唯一的三目运算符)
结合性:自右至左
优先级:13级
使用方法:表达式1 ? 表达式2 : 表达式3。
先判断表达式1是否成立,若成立取表达式2,否则取表达式3。
条件运算符相当于小型的if-else表达式
#include <stdio.h> int main() { int a,b; scanf("%d%d",&a,&b); int m = (a>b)?a:b; printf("m=%d\n",m); return 0; }
长度运算符
符号及含义:sizeof()(计算括号内数据类型或表达式的大小)
数目:无
结合性:无
优先级:2级
使用方法:sizeof(表达式) 或 sizeof(类型名)
sizeof()用于计算某类型或某表达式所占内存的大小,经常与结构体/数组等连同使用
逗号运算符
符号及含义: ,(连接多个表达式组成一个新的表达式,并将最后一个表达式的值作为整个逗号表达式的值
)
数目:未知
结合性:自左至右
优先级:15级(最低)
使用方法:表达式1, 表达式2, …, 表达式n
示例:
y = ((x=a+b),(b+c));
y 等于整个逗号表达式的值,就是表达式2的值,x是第一个表达式的值。
赋值运算符及复合赋值运算
符号及含义:=(赋值) +=(加后赋值) -=(减后赋值) *=(乘后赋值) /=(除后赋值) %=(取余后赋值) <<=(左移后赋值) >>=(右移后赋值) &=\(按位与后赋值) ^=(按位异或后赋值) |=(按位或后赋值)
数目:双目运算符(一次赋值)
结合性:自右至左
优先级:14级
使用方法:
一次赋值:待赋值 运算符 表达式。如a=3,a=5+4,a+=5等
多重赋值:将同一个值赋给多个变量的操作,如a=b=c=10。此时a,b,c都为10
注意:赋值表达式的值:被赋值变量的值,就是赋值表达式的值。
a+=1; //a=a+1;