目录
操作符
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 语言内置了丰富的操作符。
算术操作符
+ - * / %
#include <stdio.h>
int main()
{
int a = 21;
int b = 10;
int c ;
c = a + b;
printf("Line 1 - c 的值是 %d\n", c );
c = a - b;
printf("Line 2 - c 的值是 %d\n", c );
c = a * b;
printf("Line 3 - c 的值是 %d\n", c );
c = a / b;
printf("Line 4 - c 的值是 %d\n", c );
c = a % b;
printf("Line 5 - c 的值是 %d\n", c );
1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
移位操作符
<< 左移操作符>> 右移操作符注:移位操作符的操作数只能是整数。
左移操作符
移位规则: 左边抛弃、右边补0
右移操作符
移位规则:首先右移运算分两种:1. 逻辑移位左边用 0 填充,右边丢弃2. 算术移位左边用原该值的符号位填充,右边丢弃
注意:对于移位运算符,不要移动负数位,这个是标准未定义的。
位操作符
& // 按位与| // 按位或^ // 按位异或注:他们的操作数必须是整数。
例子:
#include <stdio.h>
int main()
{
int num1 = 1;
int num2 = 2;
num1 & num2;
num1 | num2;
num1 ^ num2;
return 0; }
不能创建临时变量(第三个变量),实现两个数的交换。
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a^b;
b = a^b;
a = a^b;
printf("a = %d b = %d\n", a, b);
return 0; }
赋值操作符
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
例子:
#include <stdio.h>
main()
{
int a = 21;
int c ;
c = a;
printf("Line 1 - = 运算符实例,c 的值 = %d\n", c );
c += a;
printf("Line 2 - += 运算符实例,c 的值 = %d\n", c );
c -= a;
printf("Line 3 - -= 运算符实例,c 的值 = %d\n", c );
c *= a;
printf("Line 4 - *= 运算符实例,c 的值 = %d\n", c );
c /= a;
printf("Line 5 - /= 运算符实例,c 的值 = %d\n", c );
c = 200;
c %= a;
printf("Line 6 - %= 运算符实例,c 的值 = %d\n", c );
c <<= 2;
printf("Line 7 - <<= 运算符实例,c 的值 = %d\n", c );
c >>= 2;
printf("Line 8 - >>= 运算符实例,c 的值 = %d\n", c );
c &= 2;
printf("Line 9 - &= 运算符实例,c 的值 = %d\n", c );
c ^= 2;
printf("Line 10 - ^= 运算符实例,c 的值 = %d\n", c );
c |= 2;
printf("Line 11 - |= 运算符实例,c 的值 = %d\n", c );
}
单目操作符
! |
逻辑反操作
|
+ |
正值
|
- |
负值
|
& |
取地址
|
sizeof |
操作数的类型长度(以字节为单位)
|
~ |
对一个数的二进制按位取反
|
-- |
前置、后置
--
|
++ |
前置、后置
++
|
* |
间接访问操作符
(
解引用操作符
)
|
(类型) |
强制类型转换
|
sizeof运算符
sizeof是C语言的关键字,它用来计算变量(或数据类型)在当前系统中占用内存的字节数。
sizeof不是函数,产生这样的疑问是因为sizeof的书写确实有点像函数,sizeof有两种写法:
用于数据类型:
sizeof(数据类型); printf("字符型变量占用的内存是=%d\n",sizeof(char)); // 输出:字符型变量占用的内存是=1 printf("整型变量占用的内存是=%d\n",sizeof(int)); // 输出:整型变量占用的内存是=4
数据类型必须用括号括住。
用于变量
sizeof(变量名); sizeof 变量名; int ii; printf("ii占用的内存是=%d\n",sizeof(ii)); // 输出:ii占用的内存是=4 printf("ii占用的内存是=%d\n",sizeof ii); // 输出:ii占用的内存是=4
关系操作符
>>=<<=!= 用于测试 “ 不相等 ”== 用于测试 “ 相等 ”注意:在编程过程中,== 和 = 不要写错了
逻辑操作符
&& 逻辑与 如果两个操作数都非零,则条件为真。|| 逻辑或 如果两个操作数中有任意一个非零,则条件为真。
条件操作符
exp1 ? exp2 : exp3
举个例子:
if (a > 5)
b = 3;
else
b = -3;
//将上述代码转换成表达式
a > 5 ? 3 : -3;
逗号表达式
exp1, exp2, exp3, …expN
逗号表达式,就是用逗号隔开的多个表达式。逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
下标引用、函数调用和结构成员
[ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
int arr[10];//创建数组 arr[9] = 10;//实用下标引用操作符。 [ ]的两个操作数是arr和9。
( ) 函数调用操作符
接收一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
#include <stdio.h> void test1() { printf("hehe\n"); } void test2(const char *str) { printf("%s\n", str); } int main() { test1(); //实用()作为函数调用操作符。 test2("hello bit.");//实用()作为函数调用操作符。 return 0; }
访问结构的成员操作符
. 结构体. 成员名-> 结构体指针-> 成员名#include <stdio.h> struct Stu { char name[10]; int age; char sex[5]; double score; }; void set_age1(struct Stu stu) { stu.age = 18; } void set_age2(struct Stu* pStu) { pStu->age = 18;//结构成员访问 } int main() { struct Stu stu; struct Stu* pStu = &stu;//结构成员访问 stu.age = 20;//结构成员访问 set_age1(stu); pStu->age = 20;//结构成员访问 set_age2(pStu); return 0; }
表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。
隐式类型转换
C 的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为 整型 提升 。
整型提升
表达式的整型运算要在 CPU 的相应运算器件内执行, CPU 内整型运算器 (ALU) 的操作数的字节长度一般就是 int 的字节长度,同时也是 CPU 的通用寄存器的长度。因此,即使两个 char 类型的相加,在 CPU 执行时实际上也要先转换为 CPU 内整型操作数的标准长度。通用 CPU ( general-purpose CPU )是难以直接实现两个 8 比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于 int 长度的整型值,都必须先转换为 int 或 unsigned int ,然后才能送入 CPU 去执行运算。
如何进行整体提升呢?
// 负数的整形提升char c1 = - 1 ;变量 c1 的二进制位 ( 补码 ) 中只有 8 个比特位:1111111因为 char 为有符号的 char所以整形提升的时候,高位补充符号位,即为 1提升之后的结果是:11111111111111111111111111111111// 正数的整形提升char c2 = 1 ;变量 c2 的二进制位 ( 补码 ) 中只有 8 个比特位:00000001因为 char 为有符号的 char所以整形提升的时候,高位补充符号位,即为 0提升之后的结果是:00000000000000000000000000000001// 无符号整形提升,高位补 0
算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。