C语言操作符详解
一、单目运算符
- 逻辑非运算符:
!
用于逻辑取反。
flag | ! flag |
---|---|
真 | 假 |
假 | 真 |
#include <stdio.h>
#include <stdbool.h>
int main()
{
bool flag = true;// bool类型表示真假
printf("haha\n");
if (flag)
{
printf("hehe\n");
}
return 0;
}
运行结果:
haha
hehe
#include <stdio.h>
#include <stdbool.h>
int main()
{
bool flag = true;// bool类型表示真假
printf("haha\n");
if (!flag) // 逻辑非运算符
{
printf("hehe\n");
}
return 0;
}
运算结果:
haha
位运算符和移位运算符都是在二进制上操作的。
2. 按位取反运算符:~
用于按位取反。
在二进制的数字上进行按位取反。(运算符都是在二进制的补码上操作的。)
#include <stdio.h>
int main()
{
int n = 10;
printf("~n = %d\n", ~n);
return 0;
}
/*
n = 10 源码:00000000 00000000 00000000 00001010
反码:00000000 00000000 00000000 00001010
补码:00000000 00000000 00000000 00001010
~n = -11 补码:11111111 11111111 11111111 11110101
反码:11111111 11111111 11111111 11110100
源码:10000000 00000000 00000000 00001011
*/
运行结果:
~n = -11
- 自增运算符:
++
用于增加变量的值。
无论是前置++
还是后置++
,本质上都是自增1。
#include <stdio.h>
int main()
{
int a = 5;
a++;
printf("a = %d\n", a);
return 0;
}
运行结果:
a = 6
前置++:先加1,后使用a
#include <stdio.h>
int main()
{
int a = 5;
printf("++a = %d\n", ++a);//++a使用的是加完1之后的值
printf("a = %d\n", a);
return 0;
}
运行结果:
++a = 6
a = 6
相当于:
#include <stdio.h>
int main()
{
int a = 5;
a = a + 1;
printf("a = %d\n", a);
return 0;
}
后置++:先使用,后加1。
#include <stdio.h>
int main()
{
int a = 5;
printf("a++ = %d\n", a++);//a++使用的是原来a的值
printf("a = %d\n", a);
return 0;
}
运行结果:
a++ = 5
a = 6
相当于:
#include <stdio.h>
int main()
{
int a = 5;
printf("a = %d\n", a);
a = a + 1;
printf("a = %d\n", a);
return 0;
}
- 自减运算符:
--
用于减少变量的值。
无论是前置--
还是后置--
,本质上都是自减1。
#include <stdio.h>
int main()
{
int a = 5;
a--;
printf("a = %d\n", a);
return 0;
}
运行结果:
a = 4
前置–:先减1,后使用a
#include <stdio.h>
int main()
{
int a = 5;
printf("--a = %d\n", --a);//--a使用的是减完1的值
printf("a = %d\n", a);
return 0;
}
运行结果:
–a = 4
a = 4
相当于:
#include <stdio.h>
int main()
{
int a = 5;
a = a - 1;
printf("a = %d\n", a);
return 0;
}
后置–:先使用,后减1。
#include <stdio.h>
int main()
{
int a = 5;
printf("a-- = %d\n", a--);//a--使用的是原来a的值
printf("a = %d\n", a);
return 0;
}
运行结果:
a-- = 5
a = 4
相当于:
#include <stdio.h>
int main()
{
int a = 5;
printf("a = %d\n", a);
a = a - 1;
printf("a = %d\n", a);
return 0;
}
- 负号运算符:
-
用于改变数值的符号。
#include <stdio.h>
int main()
{
int a = 5;
printf("-a = %d\n", -a);
return 0;
}
运行结果:
-a = -5
- 正号运算符:
+
用于显式标识数值的正性(通常可省略,因默认数值为正。)
#include <stdio.h>
int main()
{
int a = 5;
printf("a = %d\n", +a);
return 0;
}
运行结果:
a = 5
- 类型转换运算符:
(类型)
,用于类型转换。
#include <stdio.h>
int main()
{
double pi = 3.14;
printf("pi = %f\n\n", pi);
int s = (int)pi;
printf("s = %d\n", s);
return 0;
}
运行结果:
pi = 3.140000
s = 3
- 长度运算符:
sizeof
用于获取数据类型或变量在内存中的大小(以字节为单位)。
int main()
{
int a = 10;
printf("%zd\n", sizeof(int));//4
printf("%zd\n", sizeof(a));//4
return 0;
}
#include <stdio.h>
int main()
{
printf("%zd\n", sizeof(char));//1
printf("%zd\n", sizeof(_Bool));//1
printf("%zd\n", sizeof(short));//2
printf("%zd\n", sizeof(int));//4
printf("%zd\n", sizeof(long));//4
printf("%zd\n", sizeof(long long));//8
printf("%zd\n", sizeof(float));//4
printf("%zd\n", sizeof(double));//8
printf("%zd\n", sizeof(long double));//8
return 0;
}
二、双目操作符
1. 算术运算符:
- 加法运算符:
+
用于将两个数相加。
#include <stdio.h>
int main()
{
int a = 10;
int b = 5;
int s = a + b;
printf("s = %d\n", s);
return 0;
}
运行结果:
s = 15
- 减法运算符:
-
用于从一个数中减去另一个数。
#include <stdio.h>
int main()
{
int a = 10;
int b = 5;
int s = a - b;
printf("s = %d\n", s);
return 0;
}
运行结果:
s = 5
- 乘法运算符:
*
用于将两个数相乘。
#include <stdio.h>
int main()
{
int a = 10;
int b = 5;
int s = a * b;
printf("s = %d\n", s);
return 0;
}
运行结果:
s = 150
- 除法运算符:
/
用于将一个数除以另一个数。当除数和被除数均为整数时,结果为整数;若被除数为浮点数,则结果为浮点数。
#include <stdio.h>
int main()
{
int a = 10;
int b = 5;
int s = a / b;
printf("s = %d\n", s);
return 0;
}
运行结果:
s = 2
- 求余运算符:
%
用于计算两个数相除的余数。参与运算的两个操作数必须是整数。
#include <stdio.h>
int main()
{
int a = 10;
int b = 5;
int s = a % b;
printf("s = %d\n", s);
return 0;
}
运行结果:
s = 0
#include <stdio.h>
int main()
{
int a = 7;
int b = 5;
int s = a % b;
printf("s = %d\n", s);
return 0;
}
运行结果:
s = 2
- 自增运算符:
++
用于将变量的值增加1。
在上文中已讲述 - 自减运算符:
--
用于将变量的值减少1。
在上文中已讲述
2. 关系运算符:
- 等于运算符
==
:用于检查两个操作数是否相等。如果相等,返回1(真);否则返回0(假)
#include <stdio.h>
int main()
{
int a = 3;
printf("%d\n", a == 3);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 3;
printf("%d\n", a == 5);
return 0;
}
运行结果:
0
- 不等于运算符
!=
:用于检查两个操作数是否不相等。如果不相等,返回1(真);否则返回0(假)
#include <stdio.h>
int main()
{
int a = 3;
printf("%d\n", a != 5);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 3;
printf("%d\n", a != 3);
return 0;
}
运行结果:
0
- 大于运算符
>
:用于检查左操作数是否大于右操作数。如果是,返回1(真);否则返回0(假)
#include <stdio.h>
int main()
{
int a = 5;
int b = 3;
printf("%d\n", a > b);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 5;
int b = 3;
printf("%d\n", b > a);
return 0;
}
运行结果:
0
- 小于运算符
<
:用于检查左操作数是否小于右操作数。如果是,返回1(真);否则返回0(假)
#include <stdio.h>
int main()
{
int a = 5;
int b = 3;
printf("%d\n", b < a);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 5;
int b = 3;
printf("%d\n", a < b);
return 0;
}
运行结果:
0
- 大于等于运算符
>=
:用于检查左操作数是否大于或等于右操作数。如果是,返回1(真);否则返回0(假)
#include <stdio.h>
int main()
{
int a = 5;
int b = 3;
printf("%d\n", a >= b);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 5;
int b = 5;
printf("%d\n", a >= b);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 5;
int b = 3;
printf("%d\n", b >= a);
return 0;
}
运行结果:
0
- 小于等于运算符
<=
:用于检查左操作数是否小于或等于右操作数。如果是,返回1(真);否则返回0(假)
#include <stdio.h>
int main()
{
int a = 5;
int b = 3;
printf("%d\n", b <= a);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 5;
int b = 5;
printf("%d\n", b <= a);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 5;
int b = 3;
printf("%d\n", a <= b);
return 0;
}
运行结果:
0
3. 逻辑运算符:
- 逻辑与
&&
当且仅当两个操作数均为真(非零)时,结果为真(返回1);否则为假(返回0)
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("%d\n", a == 3 && a < b);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("%d\n", a == 5 && a < b);
return 0;
}
运行结果:
0
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("%d\n", a == 5 && a > b);
return 0;
}
运行结果:
0
- 逻辑或
||
当至少一个操作数为真时,结果为真;仅当两个操作数均为假(零)时结果为假
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("%d\n", a == 3 || a < b);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("%d\n", a == 3 || a > b);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("%d\n", a == 5 || a < b);
return 0;
}
运行结果:
1
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
printf("%d\n", a == 5 || a > b);
return 0;
}
运行结果:
0
- 逻辑非
!
单目运算符,对操作数的逻辑值取反:操作数为真时结果为假,操作数为假时结果为真
在上文中已讲述
4. 位操作运算符:
- 按位与
&
功能:两个操作数对应的二进制位均为 1 时,结果位为 1,否则为 0
int main()
{
int a = 3;
int b = -6;
int r = a & b;
printf("%d\n", r);// 2
return 0;
}
00000000000000000000000000000011 3的补码
10000000000000000000000000000110 -6的源码
11111111111111111111111111111001 -6的反码
11111111111111111111111111111010 -6的补码
00000000000000000000000000000011 3的补码
11111111111111111111111111111010 -6的补码
00000000000000000000000000000010 r的补码 --> 源码
- 按位或
|
功能:两个操作数对应的二进制位有至少一个为 1 时,结果位为 1
int main()
{
int a = 3;
int b = -6;
int r = a | b;
printf("%d\n", r);// -5
return 0;
}
00000000000000000000000000000011 3的补码
10000000000000000000000000000110 -6的源码
11111111111111111111111111111001 -6的反码
11111111111111111111111111111010 -6的补码
00000000000000000000000000000011 3的补码
11111111111111111111111111111010 -6的补码
11111111111111111111111111111011 r 的补码
10000000000000000000000000000100
10000000000000000000000000000101 r 的源码
- 按位异或
^
功能:两个操作数对应的二进制位不同时,结果位为 1;相同时为 0
int main()
{
int a = 3;
int b = -6;
int r = a ^ b;
printf("%d\n", r);// -7
return 0;
}
00000000000000000000000000000011 3的补码
10000000000000000000000000000110 -6的源码
11111111111111111111111111111001 -6的反码
11111111111111111111111111111010 -6的补码
00000000000000000000000000000011 3的补码
11111111111111111111111111111010 -6的补码
11111111111111111111111111111001 r 的补码
10000000000000000000000000000110
10000000000000000000000000000111 r 的源码
- 按位取反
~
功能:单目运算符,将操作数的所有二进制位取反(0变1,1变0)
在上文中已讲述 - 左移
<<
功能:将左操作数的二进制位向左移动右操作数指定的位数,右侧空位补 0
int main()
{
int num = -10;
int r = num << 1;
printf("%d\n", num);// -10
printf("%d\n", r);// -20
return 0;
}
10000000000000000000000000001010 -10的源码
11111111111111111111111111110101 -10的反码
11111111111111111111111111110110 -10的补码
num << 1
11111111111111111111111111101100 r 的补码
10000000000000000000000000010011 r 的反码
10000000000000000000000000010100 r 的源码
- 右移
>>
功能:将左操作数的二进制位向右移动右操作数指定的位数。
有符号数:左侧空位补符号位(算术右移)。
无符号数:左侧空位补 0(逻辑右移)。
int main()
{
int num = -10;
int r = num >> 1;
printf("%d\n", num);// -10
printf("%d\n", r);// -5
return 0;
}
num:
10000000000000000000000000001010 10的源码
11111111111111111111111111110101 10的反码
11111111111111111111111111110110 10的补码
num >> 1:
11111111111111111111111111111011 r的补码
10000000000000000000000000000100 r的反码
10000000000000000000000000000101 r的源码
5. 逗号运算符:
C语言中的逗号运算符,
是一种特殊的运算符,主要用于将多个表达式组合成一个复合表达式。
定义与返回值:
逗号运算符将多个表达式按顺序连接,从左到右依次执行,整个表达式的值为最后一个子表达式的值。
int a = (2 + 3, 5 + 4); // a 的值为9
int a, b;
a = (b = 3, b += 2, b * 5); // a是25,b是5。
三. 三目操作符
C语言中的三目运算符 ( ? : )
是唯一的三元运算符,也称为条件运算符,其核心功能是根据条件表达式的结果选择返回两个值之一。
条件表达式 ? 表达式1 : 表达式2
int a = 5, b = 10;
int max = (a > b) ? a : b; // max = 10
int num = 7;
printf("%s", (num % 2 == 0) ? "Even" : "Odd"); // 输出 "Odd"
四. 指针运算符
基础指针操作符
取地址符 &
作用:获取变量的内存地址。
int main()
{
int a = 10;
printf("%p\n", &a);//0000007C866FF994
return 0;
}
解引用符 *
作用:通过指针访问或修改其指向的内存数据。
int main()
{
int a = 10;
printf("%d\n", a);//10
int* pa = &a;
*pa = 200;
printf("%d\n", a);//200
return 0;
}
特殊指针操作符
数组名与指针
数组名是首元素的地址(等价于&arr[0]
)
int main()
{
int arr[10] = { 0 };
printf("%p\n", &arr[0]);//005EFB00
printf("%p\n", arr);//005EFB00
return 0;
}
五. 其他运算符
- 括号运算符
()
int result = 3 + 4 * 5; // 先计算4*5=20,再+3 → result=23
int result = (3 + 4) * 5; // 先计算 3+4=7,再乘5 → result=35
- 下标引用运算符
[]
int arr[5] = {10, 20, 30, 40, 50};
int a = arr[2]; // 访问第3个元素(索引从0开始),a = 30
arr[3] = 99; // 修改第4个元素的值为99
int nums[3] = {5, 7, 9};
int *ptr = nums; // 指针指向数组首地址
int val = ptr[1]; // 等价于 nums[1],val = 7
ptr[2] = 100; // 等价于 nums[2] = 100
底层逻辑:ptr[i] 等价于 *(ptr + i),通过指针偏移访问内存。
- 结构体成员访问运算符
.
和->
3.1 直接成员访问 .
语法:通过结构体变量直接访问成员
struct stu
{
char name[20];
int age;
};
struct stu s = { "cuihua", 18 };
printf("%s\n", s.name);
printf("%d\n", s.age);
//结构体变量.成员名
return 0;
}
3.2 指针成员访问 ->
语法:通过结构体指针间接访问成员(等价于(*ptr).member
)
struct stu
{
char name[20];
int age;
};
struct stu s = { "cuihua", 18 };
printf("%s\n", s.name);
printf("%d\n", s.age);
//结构体变量.成员名
struct stu* ps = &s;
//-> 结构体成员访问操作符
//结构体指针->成员名
printf("%s\n", ps->name);//(*ps).name
printf("%d\n", ps->age);//(*ps).age
return 0;
}
完结撒花🎉!