算术操作符
+ - * / %
/: 除法操作符,当除数和被除数都是整数,结果就是整数,若有一个是浮点数,则结果是浮点数。 %: 符号两端都只能是整数,返回是整除之后的余数。
移位操作符
<< 左移操作符
>> 右移操作符
操作数只能是整数
a.左移操作符
左边抛弃,右边补0(左移一位,相当于乘2)
b.右移操作符
右移操作符分为两种: (1)逻辑右移 右边抛弃,左边补0(右移一位,相当于除2) (2)算术右移 左边用原该值的符号位填充,右边丢弃 该数是负数,符号位为1,所以左边补1
位操作符
& 按位与
| 按位或
^ 按位异或
int main() {
int n = 10;
int m = 20;
printf("%d\n", n & m);
printf("%d\n", n | m);
printf("%d\n", n ^ m);
}
赋值操作符
=
int a=10;
a=20;
一定要注意区别=和==,赋值和判断相等
复合赋值符
+=
-=
*=
/=
%=
<<=
>>=
&=
|=
^=
int a=10;
a=a+20;
a+=20;
单目操作符
! 逻辑反操作
+ 正值
- 负值
& 取地址
sizeof 操作数类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 解引用操作符
int main() {
int n = -10;
int* p = NULL;
printf("%d\n", !0);
printf("%d\n", !2);
n = -n;
printf("%d\n", n);
p = &n;
printf("%d\n", sizeof(n));
return 0;
}
逻辑反操作是0或1。 前置++: 先执行++操作,再进行赋值操作
int main(){
int a=10;
int b=++a;
printf("a=%d b=%d\n",a,b);
return 0;
}
后置++: 先执行赋值操作,再进行++操作
int main(){
int a=10;
int b=a++;
printf("a=%d b=%d\n",a,b);
return 0;
}
sizeof和数组
void test1(int arr[])
{
printf("%d\n", sizeof(arr));
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(ch));
test1(arr);
test2(ch);
return 0;
}
函数传参将首元素地址传过去,只要是地址,其大小为4/8bit。而sizeof(数组名),表示整个数组的大小。
关系操作符
>
>=
<
<=
!= 用来判断不相等
== 用来判断相等
逻辑操作符
&& 逻辑与(并且)两者都要满足
|| 逻辑或(或者)至少有一个满足
逻辑与和逻辑或只有0、1两种状态。
int main() {
int n = 10;
int m = 20;
printf("%d\n", n & m);
printf("%d\n", n && m);
printf("%d\n", n | m);
printf("%d\n", n || m);
return 0;
}
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
当逻辑与的时候,有0则直接返回,后面发生短路。 当逻辑或的时候,有1则直接返回,后面发生短路。
条件操作符
exp1 ? exp2 : exp3
exp1条件为真则执行exp2,否则执行exp3
int main() {
int a = 10;
int b = 20;
printf("%d", a > b ? a : b);
return 0;
}
逗号表达式
用逗号隔开的表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果。
exp1,exp2,exp3...expN
int main() {
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
printf("%d", c);
return 0;
}
下标引用、函数调用和结构成员
[] 下标引用操作符
操作数是数组名和索引值
int arr[10];
arr[2]=5;
() 函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,其余操作数是传递给函数的参数。
访问结构体成员
. 结构体.成员名
-> 结构体指针->成员名
struct Student
{
char name[20];
int age;
};
int main() {
struct Student st[5] = {{"zhangsan",20},{"lisi",18}};
struct Student* ptr = &st;
printf("%s\n", st[1].name);
printf("%d\n", ptr->age);
return 0;
}
隐式类型转换
整型提升
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
char a,b,c;
c=a+b;
a和b先被提升为整型,然后再执行加法运算。加法运算完成后,发生截断,再赋值给c。
char a = 10;
char a=-10;
int main() {
char c = 1;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(+c));
printf("%u\n", sizeof(-c));
return 0;
}
c只要参与表达式运算就会发生整型提升。
|