1、什么是表达式?
表达式就是用来表达某个意思的式子。
在C语言中,表达式就是用运算符连接操作数的式子。
我们认为带 ;的就是语句,没有分号的就是表达式。
❤❤❤❤❤除了声明语句,所有的语句都必须在函数里面。
2、C语言中的运算符
强制类型转换:(类型名)表达式
eg:
float a = 3.6;
printf("%d\n", (int)a); //3
1)有实数相除的结果是双精度实数,两个整数相除的结果为整数,想要结果为实数,可在最前面 *1.0
1.0*3/2 ==>隐式类型转换:高精度数据与低精度数据计算时,其结果自动向高精度类型转换
unsigned int a=10; // 0~2^32
int b=-20;// -2^31~2^31-1
a+b>5; // yes 无符号数据与有符号数据运算,结果为无符号数据(高精度)
2)%运算符要求参加运算的运算对象(即操作数)为整数,结果也为整数,且不能对0取余,余数的符号与被除数的符号相同
3)算术运算符是左-->右(左结合性),赋值运算符(=)是自右-->左(右结合性)
4)用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语言规则的式子称为C算术表达式(数值表达式)
关系运算符: 双目运算符 ,结合性:左-->右,表达两个式子的关系
(>、<、>=、<=、==、!=)
1)(>、<、>=、<=)优先级相同 高于 (==,!=)优先级相同
2)用关系运算符将两个数值或数值(算术)表达式连接起来的式子,称为关系(条件)表达式
3)关系表达式的值:1(关系成立:真),0(关系不成立:假)
可以参与运算 a += (a == b)
eg: 5>4>3
-->1>3 5>4>3 语法错误,正确的书写方式:5>4 && 4>3
-->0
表示0
n > 0 && n < 60 b==a=2; // ==运算符优先级大于=,a==b的值为0或1,再=2则出现语法错误。
1010&&a<15
请写出以下程序的输出结果( 1 )
main() { int a = 100; if(a > 100) printf("%d\n", a > 100); else printf("%d\n", a <= 100); //算术表达式 }
逻辑运算符:
&&(逻辑与) 同真为真,其余为假 双目运算符 结合性:左-->右
|| (逻辑或) 同假为假,其余为真 双目运算符 结合性:左-->右
!(逻辑非) (取反) 单目运算符
1)优先级 ! > && > ||
2) 优先级:逻辑运算符 ( !)》 算术运算符 》 关系运算符 》逻辑运算符(&&与||) 》 赋值运算符(=)
3)逻辑表达式的值是一个逻辑量“真”或“假”,在判断一个量是否为“真”时,以0代表“假”, 以非0代表“真”,但是计算结果为真则一定是1
if(a>b) 则输出YES. a > b && printf("YES\n");
if(a b && printf("NO\n");
4)短路运算(惰性运算):如果事先就知道了某表达式的结果,那么该表达式就不会计算完
判断变量a、b的值均不为0的逻辑表达式为 a != 0 && b != 0
逗号运算符(双目运算符):(用于将若干个表达式连接起来,最后一个表达式的值就是整个逗号表达式的值)
格式: 表达式1,表达式2,表达式3,……表达式n
1) 求值顺序:先计算表达式1的值,在计算表达式2的值,...最后计算表达式n的值,然后整个逗号表达式的结果为表达式n的值。
2) C语言所有的运算符中,逗号运算符的优先级最低3)逗号运算符的结合性是左-->右
注意:逗号表达式与函数参数列表相区分。
例: f = (3.2,1.0) 不是逗号表达式,()优先级高于,最后=
三目运算符+逗号表达式:l1 = l1 != NULL ? (c += l1->val, l1->next) : l1;
sizeof运算符:单目运算符,求字节数运算符,不是一个函数!,是C语言唯一的关键字运算符,可以计算某一种类型数据所占内存存储单元的字节个数。
格式: sizeof(变量名或数据类型标识符) 或 sizeof 变量名或数据类型标识符
sizeof 运算的结果跟圆括号里的数据类型相关,单位是字节
sizeof(3.6) <==> sizeof(double)
sizeof(3.6f) <==> sizeof(float)short s;
sizeof(s+1) ==> sizeof(int)sizeof s // sizeof后面可以不带括号,但是不能没有空格
如果a^b=c,那么一定a^c=b、b^c=a
if(b == 5) 则(~b + 1 == -5)
位操作练习:
1)有一个int型变量 a[31:0],写一个表达式把a的第10位置1(置位),其他位不变
a |= 1<<10; // a = a | (1<<10);
2)有一个int型变量 a[31:0],写一个表达式把a的第10位清0(复位),其他位不变
a &= ~(1<<10);
3)有一个int型变量 a[31:0],写一个表达式把a的第10取反,其他位不变
a ^= 1<<10;
4)有一个int型变量 a[31:0],写一个表达式判断a的第10位是否为1
if(a & 1<<10)
{
printf("yes 1\n");
}
else
{
printf("no 1\n");
}
5)有一个int型变量 a[31:0],写一个表达式把a的[9:6]位设置为12(1100),其他位不变
step1:
a &= ~(15<<6); // [9:6]位清零
或者 a &= ~(0x0f<<6);
step2:
a |= 12<<6;6) 在C语言中,如下程序输出结果为
int a = -2<<5;
printf("a = %d\n",a); // -64
printf("a = %u\n",a); // 2^32-64
7) 取出二进制的最后一个位权为1
X&(-X)
条件运算符:(三目运算符)>赋值运算符 结合性:右---->左
格式: <表达式1>?<表达式2>:<表达式3>
求值顺序:如果表达式1的值为真,则整个条件运算符表达式的值为表达式2 的值
如果表达式1的值为假,则整个条件运算符表达式的值为表达式3 的值
注意:条件运算表达式也有 惰性运算printf("%d %d %d\n", (a>b)?(a=4):(a>b)?(b=4):(b=5),a,b); // 结果? why?
printf("%d %d %d\n", (ab)?(b=4):(b=5),a,b); // 结果? why?
tips:结合性不等于执行顺序。
赋值运算符( = ):(双目运算符) 结合性:右->左,优先级排名倒数第二
eg:
a = 5+3;
注意:赋值运算符的左边必须是“可写的地址”。在变量说明中,不允许连续给多个变量赋初值例如:int a=b=c=5; // 错误 但是赋值语句可以连续赋值。
复合的赋值运算符:赋值运算符可以和算术运算符、位运算符组合成复合的赋值运算符。
+= : a += 5 ==> a = a + 5
-=
*= : a *= 3+5 ==> a = a*(3+5)
/=
%=
&=
|=
^=
<<=
>>a=7+b+c=a+c +的运算符优先级高于=,即a=常量=常量,赋值运算符为右结合性,固常量=常量,语法错误,不三不四
若有 int i=10,j=0;则执行完语句 if (j=0)j++;else i--; i的值为多少?9 j=0(把0赋值给j)
自增、自减运算符(++ --),单目运算符
表达式的值 执行完整个表达式后i的值
i++ i i=i+1
++i i+1 i=i+1
i-- i i=i-1
--i i-1 i=i-1注意:1)应该避免使用 i = i++;
2)应该避免把自增和自减用得特别复杂,有可能会被优化1)
int i,j=1,k=2;
if (( j++|| k++)&& i++)
++优先级高于||和&&,&&优先级高于||,相当于((j++)||(i++))&&(i++), j 的值为1,所以
(j++)||(i++)的值为1
2)
int i,j=1,k=2;
if (( j++&& k++)&& i++)
先拿 j 和 k的原值&&,然后 j 和 k 再自增1,再把 j 和 k的原值&&得到的值和 i 的原值&&,最后 i 自增1
3)(a--)+b--; // 先拿a和b的原值相加,然后a和b自减1
++a+b--; // 先a自增1,然后再和b的原值相加,最后b自减1
♥指针运算符(* &) 单目运算符
♥分量运算符(. ->)
用来求结构体变量的成员变量
a.i // a是结构体变量
p->i // p是结构体指针变量
♥下标运算符( [] )
取数组中的元素
int a[10];
a[3], a[5]
⭐运算符的优先级和结合性的总结( tips:结合性不等于执行顺序)
() [] -> . 自左向右
! ~ ++ -- +-(正负号) 自右向左 单目运算符
* / % 自左向右 算术运算符
+ -
< < = > >= 自左向右 关系运算符
== !=
<< >> 自左向右 位运算符
& | ^
&& 自左向右 逻辑运算符
||
? : 自右向左 条件运算符
= 自右向左 赋值运算符
, 自左向右 逗号运算符
注意:计算表达式的时候,先判断各运算符之间的优先级,再看运算符的结合性,
同时还需要注意惰性运算,优先级如果记不住,请自觉打括号。
编程规范:
一、逗号, 之后加空格
printf("error! score[%d] = %d\n", i, score[i]);
二、分号; 之后加空格for(i = 0; i < student_num; i++)
三、关系运算符<、<=、>、>=、==、!= 前后加空格if( (score[i] >= 0) && (score[i] <= 100) )
四、赋值运算符=、+=、-=、*=、/=、%=、|=、&=、^=、>>=、<<= 前后加空格i = 0;
total_score += score[i];
ptr -= 1;
五、算术运算符+、-、*、/、%前后加空格total = n + m;
total = n - m;
total = n * m;
total = n / m;
total = n % m;
六、逻辑运算符&&、||、! 前后加空格if( (score[i] >= 0) && (score[i] <= 100) )
七、三目运算符前后加空格num = a < b ? a :b;
八、->、. 前后不加空格Studen_str->score = 100;
Studen_str.score = 100;九、if、for、while、switch等与后面的括号间应加空格,使 if 等关键字更为突出、明显
if (a >= b && c > d)
输出函数说明:
printf 函数
头文件:stdio.h
原型:int printf (const char *format,...);
format:格式控制字符串
...:可变参数列表
返回值:输出字符的数量 (最后 \n也算)
#include
int main(int argc, char *argv[]) { int n1, n2; n1 = printf("Hello World\n"); //(最后 \n也算) + 1 n2 = printf("Hello world : 123\n"); printf("n1 = %d n2 = %d\n", n1, n2); return 0; } //输出: Hello World Hello world : 123 n1 = 12 n2 = 18 //末尾\n占一个字符数量
输入函数说明:
scanf函数
头文件:stdio.h
原型:int scanf(const char *format,...);
format:格式控制字符串
...:可变参数列表
返回值:成功读入的参数个数
#include
int main(int argc, char *argv[]) { int a, b, n; printf("normal scanf, input a, b: "); n = scanf("%d%d", &a, &b); printf("a = %d, b = %d\n", a, b); printf("n = %d\n", n); printf("formal scanf, input %%dabc%%d: "); n = scanf("%dabc%d", &a, &b); //格式化读入 printf("a = %d, b = %d\n", a, b); printf("n = %d\n", n); return 0; } //输出 normal scanf, input a, b: 123 456 a = 123, b = 456 n = 2 formal scanf, input %dabc%d: 123abc456 a = 123, b = 456 n = 2
Ctrl+d:结束当前命令窗口(结束此次输入)
#include
int main(int argc, char *argv[]) { int a, b, n; printf("normal scanf, input a, b: "); n = scanf("%d%d", &a, &b); printf("a = %d, b = %d\n", a, b); printf("n = %d\n", n); printf("formal scanf, input %%dabc%%d: "); n = scanf("%dabc%d", &a, &b); //格式化读入 printf("a = %d, b = %d\n", a, b); printf("n = %d\n", n); n = scanf("%d", &a); printf("n = %d\n", n); n = scanf("%d", &a); printf("n = %d\n", n); n = scanf("%d", &a); printf("n = %d\n", n); n = scanf("%d", &a); printf("n = %d\n", n); n = scanf("%d", &a); printf("n = %d\n", n); n = scanf("%d", &a); printf("n = %d\n", n); n = scanf("%d", &a); printf("n = %d\n", n); n = scanf("%d", &a); printf("n = %d\n", n); printf("EOF = %d\n", EOF); return 0; } //输出: normal scanf, input a, b: 123 456 a = 123, b = 456 n = 2 formal scanf, input %dabc%d: 123abc456 a = 123, b = 456 n = 2 1 n = 1 2 n = 1 3 n = 1 4 n = 1 n = -1 n = -1 n = -1 n = -1 EOF = -1
#include
int main(int argc, char *argv[]) { int n, digit; scanf("%d", &n); digit = printf("%d", n); printf(" has %d digit(s)\n", digit); return 0; }
int main(int argc, char *argv[])
{
char s[100];
scanf("%[^\n]", s);
int n;
n = printf("%s", s);
printf(" : %d\n", n);
return 0;
}
sscanf函数:从字符串中读取数据 (将字符串信息转换成其他信息)
#include
int main(int argc, char *argv[])
{
char s[100] = "123 456 789";
int a, b, c;
sscanf(s, "%d%d%d", &a, &b, &c);
printf("a = %d, b = %d, c = %d\n", a, b, c); //123, 456, 789
return 0;
}
sprintf函数:将输出的内容输出到一个字符串中去(将其他信息转换成字符串信息)
#include
int main(int argc, char *argv[])
{
char str[100] = "192.168.1.245";
int a, b, c, d;
sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d);
sprintf(str, "%d:%d:%d:%d", a, b, c, d);
printf("str = %s", str); //192:168:1:245
return 0;
}
#include
int main(int argc, char *argv[])
{
char s[100], t[100];
scanf("%[^\n]", s);
int n;
n = sprintf(t, "| %s |", s);
for(int i = 0; i < n; i++) printf("-");
printf("\n");
printf("| %s |\n", s);
for(int i = 0; i < n; i++) printf("-");
printf("\n");
return 0;
}