目录
C语言入门总结
1.基本格式
引入头文件:#include <stdio.h>
C语言程序的入口点:main函数
printf函数调用:printf(内容) 打印到控制台
第一个项目:创建项目之后自动生成了一个.c
文件,这个就是我们编写的程序代码文件:
#include <stdio.h>
int main() { //入口
printf("Hello World!"); //打印
return 0; //可有可无
}
操作系统需要执行我们的程序,但是我们的程序中可能写了很多很多的代码,那么肯定需要知道从哪里开始执行才可以,也就是程序的入口,所以我们需要提供一个入口点,我们的C语言程序入口点就是main
函数。
2.基本数据类型(6种)
整形int、长整型long、短整型short、单精度浮点型float、双精度浮点型double、字符型char。
-
位Bit 计算机存储信息的最小单位: 位 bit (比特):存放一位二进制数,即 0 或 1,最小的存储单位。
-
字节byte 计算机存储容量基本单位是字节:字节 byte:8个二进制位(bit)为一个字节(B). 8bit=1Byte
一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。英文标点占一个字节,中文标点占两个字节。
整数类型
我们首先来看看整数类型,整数就是不包含小数点的数据,比如1
,99
,666
等数字,整数包含以下几种类型:
-
int - 占用 4 个字节,32个bit位,能够表示 -2,147,483,648 到 2,147,483,647 之间的数字,默认一般都是使用这种类型
-
long - 占用 8 个字节,64个bit位。
-
short - 占用2个字节,16个bit位。
浮点类型
浮点类一般用于保存小数,不过为啥不叫小数类型而是浮点类型呢?因为我们的一个小数分为整数部分和小数部分,我们需要用一部分的bit位去表示整数部分,而另一部分去表示小数部分,至于整数部分和小数部分各自占多少并不是固定的,而是浮动决定的(在计算机组成原理中会深入学习,这里就不多介绍了)
-
float - 单精度浮点,占用4个字节,32个bit位。
-
double - 双精度浮点,占用8个字节,64个bit位。
字符类型
除了保存数字之外,C语言还支持字符类型,我们的每一个字符都可以使用字符类型来保存:
-
char - 占用1个字节(-128~127),可以表示所有的ASCII码字符,每一个数字对应的是编码表中的一个字符:
编码表中包含了所有我们常见的字符,包括运算符号、数字、大小写字母等(注意只有英文相关的,没有中文和其他语言字符,包括中文的标点符号也没有)
某些无法直接显示的字符(比如换行,换行也算一个字符)需要使用转义字符来进行表示:
3.原码、反码、补码
十进制转二进制的两种方法:
方法1:余数短除法除以二
方法2:降二次幂及减法混合运算
原码:
上面我们说了实际上所有的数字都是使用0和1这样的二进制数来进行表示的,但是这样仅仅只能保存正数,那么负数怎么办呢?0正1负
比如现在一共有4个bit位来保存我们的数据,为了表示正负,我们可以让第一个bit位专门来保存符号,这样,我们这4个bit位能够表示的数据范围就是:
-
最小:1111 => - (2^2+2^1+2^0) => -7
-
最大:0111 => + (2^2+2^1+2^0) => +7 => 7
虽然原码表示简单,但是原码在做加减法的时候,很麻烦!以4bit位为例:
1+(-1) = 0001 + 1001 怎么让计算机去计算? (虽然我们知道该去怎么算,但是计算机不知道,计算机顶多知道1+1需要进位!)
我们得创造一种更好的表示方式!于是我们引入了反码:
反码:
正数的反码是其本身 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反 经过上面的定义,我们再来进行加减法:
1+(-1) = 0001 + 1110 = 1111 => -0 (得到的结果是反码,然后变成原码1000 直接相加,这样就简单多了!)
思考:1111代表-0,0000代表+0,在我们实数的范围内,0有正负之分吗?
0既不是正数也不是负数,那么显然这样的表示依然不够合理!
补码:
根据上面的问题,我们引入了最终的解决方案,那就是补码,定义如下:
正数的补码就是其本身 (不变!) 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1) 其实现在就已经能够想通了,-0其实已经被消除了!我们再来看上面的运算:
1+(-1) = 0001 + 1111 = (1)0000 => +0 (现在无论你怎么算,也不会有-0了!)
所以现在,4bit位能够表示的范围是:-8~+7(C使用的就是补码!) -8(1000)
补码变成原码的方式是:正数的补码与原码一致,负数的补码按位取反加1,符号位不变
反码变成原码的方式是:正数的反码与原码一致,负数的补码按位取反,符号位不变
4.变量
变量的创建和使用
不论是使用哪种高级程序语言编写程序,变量都是其程序的基本组成单位。声明变量的格式为:
数据类型 变量名称 = 初始值; //其中初始值可以不用在定义变量时设定 数据类型 变量名称; // = 是赋值操作,可以将等号后面的值赋值给前面的变量,等号后面可以直接写一个数字(常量)、变量名称、算式
比如我们现在想要声明一个整数类型的变量:
int a = 1;// 定义了一个整型变量,取名为 a, 并赋值为 1 (强数据类型语言)
int b = 3;// 定义了一个整型变量,取名为 b, 并赋值为 3
b = 89;// 给变量赋值 为 89
int a = 10, b = 20; //多个变量可以另起一行编写,也可以像这样用逗号隔开,注意类型必须是一样的
变量使用注意事项:
-
变量表示内存中的一个存储区域(不同的数据类型,占用的空间大小不一样)
-
该区域有自己的 名称 和 类型
-
变量必须先声明,后使用
-
该区域的数据可以在同一类型范围内不断变化
-
变量在同一个作用域内不能重名
-
变量三要素 (变量名+值+数据类型)
变量的数据类型:
-
每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间(使用字节多少表示)。
-
数据类型一览图
格式化打印:除了使用%d
打印有符号整数之外,还有其他的:
格式控制符 | 说明 |
---|---|
%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 类型的整数 |
%hx、%x、%lx %hX、%X、%lX | 以十六进制、不带前缀、无符号的形式输出 short、int、long 类型的整数。如果 x 小写,那么输出的十六进制数字也小写;如果 X 大写,那么输出的十六进制数字也大写。 |
%#hx、%#x、%#lx %#hX、%#X、%#lX | 以十六进制、带前缀、无符号的形式输出 short、int、long 类型的整数。如果 x 小写,那么输出的十六进制数字和前缀都小写;如果 X 大写,那么输出的十六进制数字和前缀都大写。 |
%f、%lf | 以十进制的形式输出 float、double 类型的小数 |
%e、%le %E、%lE | 以指数的形式输出 float、double 类型的小数。如果 e 小写,那么输出结果中的 e 也小写;如果 E 大写,那么输出结果中的 E 也大写。 |
%g、%lg %G、%lG | 以十进制和指数中较短的形式输出 float、double 类型的小数,并且小数部分的最后不会添加多余的 0。如果 g 小写,那么当以指数形式输出时 e 也小写;如果 G 大写,那么当以指数形式输出时 E 也大写。 |
%s | 输出一个字符串 |
来看一个例子:
#include <stdio.h>
int main() {
char c = 127; //已经到达c的最大值了
c = c + 1; //我不管,我就要再加
printf("%d", c); //这时会得到什么结果?
}
//-128
怎么127加上1还变成-128了呢?这是由于位数不够,导致运算结果值溢出:
-
127 + 1= 01111111 + 1
-
由于现在是二进制,满2进1,所以最后变成
-
10000000 = 补码形式的 -128
所以,了解上面这些计算机底层原理是很重要的,我们能够很轻松地知道为什么会这样。
在我们的运算中,可能也会存在一些一成不变的值,比如π
的值永远都是3.1415....
,在我们的程序中,也可以使用这样不可变的变量,我们成为常量。
定义常量和变量比较类似,但是需要在前面添加一个const
关键字,表示这是一个常量:
可以看到,常量在一开始设定初始值后,后续是不允许进行修改的。
无符号数
我们知道,所有的数据底层都是采用二进制来进行保存的,而第一位则是用于保存符号位,但是如果我们不考虑这个符号位,那么所有的数都是按照正数来表示,比如考虑了符号位的char
类型:
-
考虑符号表示范围:-128~127
-
不考虑符号:0~255
我们也可以直接使用这些不带符号位的数据类型:
int main() {
unsigned char c = -65; //数据类型前面添加unsigned关键字表示采用无符号形式
printf("%u", c); //%u以无符号形式输出十进制数据
}
//191
可以看到这里给了无符号char类型c一个-65的值,但是现在很明显符号位也是作为数值的表示部分,所以结果肯定不是-65:
我们来看看为什么得到的是191这个数字。首先char类型占据一个字节,8个bit位:
-
00000000 -> 现在赋值-65 -> -65的补码形式 -> 10111111
-
由于现在没有符号位,一律都是正数,所以,10111111 = 128 + 32 + 16 + 8 + 4 + 2 + 1 = 191
我们也可以直接以无符号数形式打印:
#include <stdio.h>
int main() {
int i = -1;
printf("%u", i); //%u以无符号形式输出十进制数据
}
//
得到无符号int的最大值。
类型转换(隐式、显式)
一种类型的数据可以转换为其他类型的数据,这种操作我们称为类型转换,类型转换分为自动类型转换和强制类型转换,比如我们现在希望将一个short类型的数据转换为int类型的数据:
#include <stdio.h>
int main() {
short s = 10;
int i = s; //直接将s的值传递给i即可,但是注意此时s和i的类型不同
}
这里其实就是一种自动类型转换,自动类型转换就是编译器隐式地进行的数据类型转换,这种转换不需要我们做什么,我们直接写就行,会自动进行转换操作。
float a = 3; //包括这里我们给的明明是一个int整数3但是却可以赋值给float类型,说明也是进行了自动类型转换
如果我们使用一个比转换的类型最大值都还要大的值进行类型转换,比如:
#include <stdio.h>
int main() {
int a = 511;
char b = a; //最大127
printf("%d", b);
}
//-1
很明显char类型是无法容纳大于127的数据的,因为只占一个字节,而int占4个字节,如果需要进行转换,那么就只能丢掉前面的就只保留char所需要的那几位了,所以这里得到的就是-1:
-
511 = int -> 00000000 00000000 00000001 11111111
-
char -> 11111111 -> -1 (得到的是补码)
我们也可以将整数和小数类型的数据进行互相转换:
#include <stdio.h>
int main() {
int a = 99;
double d = a;
printf("%f", d);
}
//99.000000
不过这里需要注意的是,小数类型在转换回整数类型时,会丢失小数部分(注意,不是四舍五入,是直接丢失小数!):
#include <stdio.h>
int main() {
double a = 3.14;
int b = a; //这里编译器还提示了黄标,我们可以通过之后讲到的强制类型转换来处理
printf("%d", b);
}
//3
除了赋值操作可以进行自动类型转换之外,在运算中也会进行自动类型转换,比如:
#include <stdio.h>
int main() {
float a = 2;
int b = 3;
double c = b / a; // "/" 是除以的意思,也就是我们数学中的除法运算,这里表示b除以a
printf("%f", c);
}
//1.50000
可以看到,这里得到的结果是小数1.5,但是参与运算的既有整数类型,又有浮点类型,结果为什么就确定为浮点类型了呢?这显然是由于类型转换导致的。那么规则是什么呢?
-
不同的类型优先级不同(根据长度而定)
-
char和short类型在参与运算时一律转换为int再进行运算。
-
浮点类型默认按双精度进行计算,所以就算有float类型,也会转换为double类型参与计算。
-
当有一个更高优先级的类型和一个低优先级的类型同时参与运算时,统一转换为高优先级运算,比如int和long参与运算,那么int转换为long再算,所以结果也是long类型,int和double参与运算,那么先把int转换为double再算。
我们接着来看看强制类型转换,我们可以为手动去指定类型,强制类型转换格式如下:
(强制转换类型) 变量、常量或表达式;
比如:
#include <stdio.h>
int main() {
int a = (int) 2.5; //2.5是一个double类型的值,但是我们可以强制转换为int类型赋值给a,强制转换之后小数部分丢失
printf("%d", a);
}
我们也可以对一个算式的结果进行类型转换:
#include <stdio.h>
int main() {
double a = 3.14;
int b = (int) (a + 2.8); //注意得括起来表示对整个算式的结果进行类型转换(括号跟数学中的挺像,也是提升优先级使用的,我们会在运算符部分详细讲解),不然强制类型转换只对其之后紧跟着的变量生效
printf("%d", b);
}
在我们需要得到两个int相除之后带小数的结果时,强制类型转换就显得很有用:
#include <stdio.h>
int main() {
int a = 10, b = 4;
double c = a / b; //不进行任何的类型转换,int除以int结果仍然是int,导致小数丢失
double d = (double) a / b; //对a进行强制类型转换,现在是double和int计算,根据上面自动类型转换规则,后面的int自动转换为double,结果也是double了,这样就是正确的结果了
printf("不进行类型转换: %f, 进行类型转换: %f", c, d);
}
合理地使用强制类型转换,能够解决很多情况下的计算问题。
5.运算符
基本运算符
基本运算符包含我们在数学中常用的一些操作,比如加减乘除,分别对应:
-
加法运算符:+
-
减法运算符:-
-
乘法运算符:*
-
除法运算符:/(注意不是“\”,看清楚一点)
当然,还有我们之前使用的赋值运算符=
,我们先来看看赋值运算符的使用,其实在之前我们已经学习过了:
变量 = 值 //其中,值可以直接是一个数字、一个变量、表达式的结果等
实际上等号左边的内容准确的说应该是一个左值,不过大部分情况下都是变量.
最简单的用法,对一个变量进行赋值操作,也可以连续赋值
int a=10;
int a, b;
a = b = 20;
可以看出,实际上=
运算除了赋值之外,和加减乘除运算一样也是有结果的,比如上面的 a = 就是b = 20 运算的结果(可以看着一个整体),只不过运算的结果就是b被赋值的值,也就是20。
当然也可以像数学中那样写在一个数或是变量的最前面,表示是正数:
int a = +10, b = +5;
int c= -10;
不过默认情况下就是正数,所以没必要去写一个+号。减法运算符其实也是一样的.
取模运算:
#include <stdio.h>
int main() {
int a = 20, b = 8;
printf("%d", a % b); //取模运算实际上就是计算a除以b的余数
}
在C中没有指数相关的运算符(比如要计算5的10次方)。a^2不是指数运算,^是另一个运算符。
运算符优先级
在数学中,加减运算的优先级是没有乘除运算优先级高的,所以我们需要先计算那些乘除法,最后再来进行加减法的计算,而C语言中也是这样,运算符之间存在优先级概念。我们在数学中,如果需要优先计算加减法再计算乘除法,那么就需要使用括号来提升加减法的优先级,C语言也可以。C语言也可以:
#include <stdio.h>
int main() {
int a = 20, b = 10;
printf("%d", (a + a) * b); //优先计算 a + a 的结果,再乘以 b
}
那要是遇到多重的呢?类似于下面的这种:
数学上的写法:[1 - (3 + 4)] x (-2 ÷ 1) = ?
那么我们在C中就可以这样编写:
#include <stdio.h>
int main() {
printf("%d", (1 - (3 + 4)) * (-2 / 1)); //其实写法基本差不多,只需要一律使用小括号即可
}
//12
这样,我们就可以通过()
运算符,来提升运算优先级了。
我们来总结一下,上面运算符优先级如下,从左往右依次递减:
-
()
>+ - (做符号表示,比如-9)
>* / %
>+ - (做加减运算)
>=
根据上面的优先级,我们来看看下面a
的结果是什么:
int c;
int a = (3 + (c = 2)) * 6;
//30
int b, c;
int a = (b = 5, c = b + 8); //逗号运算符从前往后依次执行,赋值结果是最后边的结果
//13
自增自减运算符
我们可以快速使用自增运算符来将变量的值+1
,正常情况下我们想要让一个变量值自增需要:
int a = 10;
a = a + 1;
//替换为:
int a = 10;
++a; //使用自增运算符,效果等价于 a = a + 1
并且它也是有结果的,除了做自增运算之外,它的结果是自增之后的值:
#include <stdio.h>
int main() {
int a = 10;
//int b = a = a + 1; 下面效果完全一致
int b = ++a;
printf("a=%d,b=%d",a,b); //a=11,b=11
}
当然我们也可以将自增运算符写到后面,和写在前面的区别是,它是先返回当前变量的结果,再进行自增的,顺序是完全相反的:
#include <stdio.h>
int main() {
int a = 10;
int b = a++; //写在后面和写在前面是有区别的 ++a先自增然后得到结果,a++是先得结果在自增
printf("a = %d, b = %d", a, b); //a=11,b=10
}
重点内容:自增运算符
++
在前,那么先自增再出结果;自增运算符++
在后,那么先出结果再自增。
那要是现在我们不想自增1而是自增2或是其他的数字呢?我们可以使用复合赋值运算符,正常情况下依然是使用普通的赋值运算符:
int a = 10;
a = a + 5;
//简写:
int a = 10;
a += 5;
效果和上面是完全一样的,并且得到的结果也是在自增之后的:
#include <stdio.h>
int main() {
int a = 10;
int b = a += 5;
printf("a = %d", b);
}
复合赋值运算符不仅仅支持加法,还支持各种各样的运算:
#include <stdio.h>
int main() {
int a = 10;
a %= 3; //可以复合各种运算,比如加减乘除、模运算、包括我们我们还要讲到的位运算等
printf("a = %d", a);
}
当然,除了自增操作之外,还有自减操作:
#include <stdio.h>
int main() {
int a = 10;
a--; //--是自减操作,相当于a = a - 1,也可以在前后写,规则和上面的自增是一样的
printf("a = %d", a);
int a=10;
printf("a = %d",a--+--a); //a--是10 a=9 --a=8 所以a--+--a=18
}
注意自增自减运算符和+
、-
做符号是的优先级一样,仅次于()
运算符,所以在编写时一定要注意:
#include <stdio.h>
int main() {
int a = 10;
int b = 5 * --a;
printf("b = %d", b);
}
位运算符
乘法运算符*
,当我们想要让一个变量的值变成2倍,只需要做一次乘法运算即可:
int a = 10;
a *= 2; //很明显算完之后a就是20了
//利用位运算来快速进行计算:
int a = 10;
a = a << 1; //也可以写成复合形式 a <<= 1
我们会发现这样运算之后得到的结果居然也是20,这是咋算出来的呢?实际上<<
是让所有的bit位进行左移操作,上面就是左移1位,我们可以来看看:
-
10 = 00001010 现在所以bit位上的数据左移一位 00010100 = 20 二进制左移一位相当于乘2
-
00005=00050=00500 十进制左移一位相当于乘以10.
就像我们在十进制中,做乘以10的操作一样:22乘以10那么就直接左移了一位变成220,而二进制也是一样的,如果让这些二进制数据左移的话,那么相当于在进行乘2的操作。
比如:
#include <stdio.h>
int main() {
int a = 6;
a = a << 2; //让a左移2位,实际上就是 a * 2 * 2,a * 2的平方(类比十进制,其实还是很好理解的)
// a=a<<3; //a左移3位 48
printf("a = %d", a);//24
}
当然能左移那肯定也可以右移:
#include <stdio.h>
int main() {
int a = 6;
a = a >> 1; //右移其实就是除以2的操作
printf("a = %d", a);
}
10 = 00001010
右移 00000101 2的2次+2的0次=5
当然除了移动操作之外,我们也可以进行按位比较操作,先来看看按位与操作:
#include <stdio.h>
int main() {
int a = 6, b = 4;
int c = a & b; //按位与操作
printf("c = %d", c);
}
按位与实际上也是根据每个bit位来进行计算的:
-
4 = 00000100
-
6 = 00000110
-
按位与实际上就是让两个数的每一位都进行比较,如果两个数对应的bit位都是1,那么结果的对应bit位上就是1,其他情况一律为0
-
所以计算结果为:00000100 = 4
除了按位与之外,还有按位或运算:
int a = 6, b = 4;
int c = a | b;
-
4 = 00000100
-
6 = 00000110
-
按位与实际上也是让两个数的每一位都进行比较,如果两个数对应bit位上其中一个是1,那么结果的对应bit位上就是1,其他情况为0。
-
所以计算结果为:00000110 = 6
还有异或和按位非(按位否定):
异或:
-
4 = 00000100
-
6 = 00000110
-
a^b=00000010
int a = 6, b = 4;
int c = a ^ b; //注意^不是指数运算,表示按位异或运算,让两个数的每一位都进行比较,如果两个数对应bit位上不同时为1或是同时为0,那么结果就是1,否则结果就是0,所以这里的结果就是2
a = ~a; //按位否定针对某个数进行操作,它会将这个数的每一个bit位都置反,0变成1,1变成0,猜猜会变成几
char c=0;
c=~c;
printf("c=%d",c); //c=-1
c=00000000
~c 11111111 补码形式。
按位运算都是操作数据底层的二进制位来进行的。
逻辑运算符
逻辑运算符主要用到流程控制语句中。逻辑运算符用于计算真和假,比如今天要么下雨要么不下雨,现在我们想要在程序中判断一下是否下雨了,这时就需要用到逻辑运算符,我们来举个例子:
#include <stdio.h>
int main() {
int a = 10;
_Bool c = a < 0; //我们现在想要判断a的值是否小于0,我们可以直接使用小于符号进行判断,最后得到的结果只能是1或0
//虽然结果是一个整数,但是这里推荐使用_Bool类型进行接收,它只能表示0和1(更加专业一些)
printf("c = %d", c);
}
实际上在C语言中,0一般都表示为假,而非0的所有值(包括正数和负数)都表示为真,上面得到1表示真,0表示假。
除了小于符号可以判断大小之外,还有:<
、<=
、>=
、>
比如我们现在想要判断字符C是否为大写字母:
#include <stdio.h>
int main() {
char c = 'D';
printf("c是否为大写字母:%d", c >= 'A'); //由于底层存储的就是ASCII码,这里可以比较ASCII码,也可以写成字符的形式
}
但是我们发现,现在我们的判断只能判断一个条件,也就是说只能判断c是否是大于等于'A'的,但是不能同时判断c的值是否是小于等于'Z'的,所以这时,我们就需要利用逻辑与和逻辑或来连接两个条件了:
#include <stdio.h>
int main() {
char c = 'D';
printf("c是否为大写字母:%d", c >= 'A' && c <= 'Z'); //使用&&表示逻辑与,逻辑与要求两边都是真,结果才是真
}
又比如现在我们希望判断c是否不是大写字母:
#include <stdio.h>
int main() {
char c = 'D';
printf("c是否不为大写字母:%d", c < 'A' || c > 'Z'); //使用||表示逻辑或,只要两边其中一个为真或是都为真,结果就是真
}
当然我们也可以判断c是否为某个字母:
#include <stdio.h>
int main() {
char c = 'D';
printf("c是否为字母A:%d", c == 'A'); //注意判断相等时使用==双等号
}
判断不相等也可以使用:
printf("c是否不为字母A:%d", c != 'A');
我们也可以对某个结果取反:
#include <stdio.h>
int main() {
int i = 20;
printf("i是否不小于20:%d", !(i < 20)); //使用!来对结果取反,注意!优先级很高,一定要括起来,不然会直接对i生效
}
这里要注意一下!
如果直接作用于某个变量或是常量,那么会直接按照上面的规则(0表示假,非0表示真)非0一律转换为0,0一律转换为1。
三目运算符:
这里我们可以结合三目运算符来使用这些逻辑运算符:对于条件表达式b ? x : y,先计算条件b,然后进行判断。如果b的值为true,计算x的值,运算结果为x的值;否则,计算y的值,运算结果为y的值。
#include <stdio.h>
int main() {
int i = 0;
char c = i > 10 ? 'A' : 'B'; //三目运算符格式为:expression ? 值1 : 值2,返回的结果会根据前面判断的结果来的
//这里是判断i是否大于10,如果大于那么c的值就是A,否则就是B
printf("%d", c);
}
最后,我们来总结一下前面认识的所有运算符的优先级,从上往下依次降低:
运算符 | 解释 | 结合方式 |
---|---|---|
() | 同数学中的括号,直接提升到最高优先级 | 由左向右 |
! ~ ++ -- + - | 否定,按位否定,增量,减量,正负号 | 由右向左 |
* / % | 乘,除,取模 | 由左向右 |
+ - | 加,减 | 由左向右 |
<< >> | 左移,右移 | 由左向右 |
< <= >= > | 小于,小于等于,大于等于,大于 | 由左向右 |
== != | 等于,不等于 | 由左向右 |
& | 按位与 | 由左向右 |
^ | 按位异或 | 由左向右 |
| | 按位或 | 由左向右 |
&& | 逻辑与 | 由左向右 |
|| | 逻辑或 | 由左向右 |
? : | 条件 | 由右向左 |
= += -= *= /= &= ^= |= <<= >>= | 各种赋值 | 由右向左 |
, | 逗号(顺序) | 由左向右 |