操作符
1.算术操作符
(1)、基本的操作的操作符
这几种基本的算术运算符,就不必介绍了
- 加号(+)
- 减号(-)
- 乘号(*)
(2)、除号(/)
除号的使用,求得的是商
eg:
#include<stdio.h>
int main()
{
float c = 6.0/5.0;
printf("%f",c);
return 0;
}
上面的结果会出现 warning C4305: “=”: 从“double”到“float”截断
解决
float c = 6.0f / 5.0f;
(3)、取模(%)
取模操作符的两个操作数必须为整数,返回的是整除之后的余数。
#include<stdio.h>
int main()
{
int c = 6/5;
printf("%d",c);
return 0;
}
2.移位操作符
(1)、 左移操作符(<<)
左移操作符 移位规则
左边抛弃,右边补0
代码如下:
#include<stdio.h>
int main()
{
int c = 2;
int a = c << 1;
printf("%d",a);
return 0;
}
算出来的结果为 4
因为四个字节 所以2的二进制码为:-00000000000000000000000000000010,
—000000000000000000000000000000100
(2)、 右移操作符(>>)
右移操作符 移位规则
右边抛弃,左边补0
代码如下:
#include<stdio.h>
int main()
{
int c = 2;
int a = c >> 1;
printf("%d",a);
return 0;
}
算出来的结果为:1
由上可得 00000000 00000000 00000000 00000010
------ – —00000000000000000000000000000000010
右移操作符分为:
1.算术右移
右边丢弃,左边补原符号位
2.逻辑右移
右边丢弃,左边补0
大多数我们都是应用的都是算术右移
3.位操作符
- 按位与(&)
- 按位或(|)
- 按位异或(^)
按位与,或,异或都是按照二进制来进行的
- 与(&): 0 1为0,0 0为0,1 1为1
- 或(|):0 1为1,0 0为0, 1 1为1
- 异或(^):0 1为1,1 1为0,0 0为0
例如下面的例子:
#include<stdio.h>
int main()
{
int a = 3;
int b = 5;
int c = a & b;
int d = a | b;
int e = a ^ b;
printf("%d,%d,%d",c,d,e);
return 0;
}
打印的结果为 1,7,6
因为a = 3的二进制位为- 0011,b的二进制位为- 0101
按照上面的原则就可以分别得到各种结果:
与(&):---------0001-------1
或(|):----------0111--------7
异或(^):------0110--------6
根据上面的原则有一道题非常有趣:
交换两个int 变量的值,不能使用第三个变量,即a = 3,b = 5,交换之后a = 5, b = 3;
这道题目我们就可以根据上面的原则就可以解决出来:
#include<stdio.h>
int main()
{
int a = 3;
int b = 5;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d,b = %d",a,b);
return 0;
}
打印的结果为:a = 5,b = 3
4.赋值操作符
(1)、简单的赋值操作符
例如:
int a = 10;
char ch = 'a';
float a = 3.0;
(2)、复合的赋值操作符
+= -= *= /= %= >>= <<= &= |= ^=
这些运算符都可以写成符合的效果。
#include<stdio.h>
int main()
{
int a = 3;
a = a + 4;
printf("a = %d",a);
return 0;
}
#include<stdio.h>
int main()
{
int a = 3;
a+ = 4;
printf("a = %d",a);
return 0;
}
这两种形式都是相同的结果
5.单目操作符
(1)、(!、 -、 + 、(类型))的应用
- ! ------------逻辑反操作
- - ------------负值
- + -----------正值
- &-----------取地址
- (类型)----强制类型转化
1.逻辑反的使用(!)
if(a == 3) printf("我要学习!");
if(a != 3) printf("我不学习!");
2.减和加(- +)
int a= 3; a = - a;
int a = 4; a = + a;
+号一般都是省略掉
3.强制类型转化 --(类型)
int a = 5.21; //这样就会报错
int a = (int)5.21; //强制类型转化
(2)、(sizeof() 、~)的应用
1. sizeof
1 、计算某一类型或者变量的大小,单位是字节。
2、sizeof是一个操作符,不是一个函数。
3、传递给数组的名后,计算的是整个数组的大小。
4、sizeof括号中的表达式是不参与运算的。
5、sizeof遇见数组传参
6、sizeof计算地址的大小的时候,4/8个字节。
int a = 3;
printf("%d",sizeof(a)); //打印的结果为4
int a = 3;
printf("%d",sizeof(int)); //打印的结果为4
int a[10] = { 0 };
printf("%d",sizeof(arr)); //打印的结果为40
#include<stdio.h>
int main()
{
short a = 2;
int b = 5;
printf("%d",sizeof(a = b + 2)); //计算的结果为2
printf("%d",a); a = 2
return 0;
}
上面的原因是因为一个源文件(.c)成为一个可执行文件(.exe)需要经过:编译–链接—运行。
上面的式子 b + 2,是在运行期间才可以运行的,但是sizeof计算的大小的时候是在编译期间运算的,即在上面的大小仅仅取决于a,b + 2的式子没有参与运算。
#include<stdio.h>
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)); //40
printf("%d\n",sizeof(ch)); //10
test1(arr); //8
test2(ch); //8
return 0;
}
上面的传参都是指针变量—在同一平台下他们的大小都是相同的
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "xiao meng";
printf("%d\n",sizeof(arr)); // 10
//计算的是数组占空间的大小,后面的'\0'同样也计算在内
printf("%d\n",strlen(arr)); // 9
//计算'\0'前面的字符占的大小
return 0;
}
strlen 函数的为**size_t strlen ( const char * str )**,即传给函数的是一个地址
char arr[] = {'a','c','t','e'};
printf("%d ",strlen(arr));//随机值
printf("%d ",strlen(*arr));//报错
printf("%d ",strlen(&arr));//随机值
printf("%d ",strlen(&arr + 1));//随机值减4
printf("%d ",strlen(&arr[0] + 1));//随机值减1,即从'c'开始往后面计算
int arr[3][4] = { {1,3,5,4},{2,4,7,5},{5,6,8,7} };
printf("%d \n", sizeof(arr));//48整个数组的大小
printf("%d \n", sizeof(arr + 1));//arr没有取地址,也没有单独的放在sizeof中,
//arr就表示数组首地址,即第一行地址,arr + 1即为第二行地址
printf("%d \n", sizeof(*(arr + 1)));//第二行元素大小
//*(arr + 1)拿到的是整个第二行地址,*(*(arr + 1))是第二行第一个元素
printf("%d \n", sizeof(*arr));//没有取地址,也没有单独的放在sizeof中,
//arr表示数组首地址即第一行地址,*arr即表示第一行元素的大小
printf("%d \n", sizeof(arr[0]));//表示第一行的元素的大小
printf("%d \n", sizeof( *(arr[0] + 1) ));//表示第一行第一个元素
//和arr[0][0]表示的方法相同
printf("%d \n", sizeof(&arr[0] + 1) );第二行的地址
printf("%d \n", sizeof( *(&arr[0] + 1) ));第二行元素的大小
printf("%d \n", sizeof(arr[0] + 1));// arr[0]没有单独放在sizeof中,也没有取地址,
//即为第一行第一个元素的地址
printf("%d \n", sizeof(arr[0][0]));第一行第一个元素的大小
printf("%d \n", sizeof(arr[3]));第四行元素的大小,(其实不存在)
//但也能通过类型计算
区分一下sizeof 和 strlen的不同的作用
2.~
~ 对一个数的二进制按位取反
int a = -1;
int b = ~ a;
printf("%d",b); //结果为0
-1在内存的以补码的形式存储:11111111 11111111 11111111 11111111
按位取反后为:00000000 00000000 00000000 00000000
即可得到结果为0
(3)、(-- 、++)的应用
1.后置++(- -)
后置++(- -)先使用,后++(- -)
int a = 5;
int b = a++;
printf("%d",b);// 5
printf("%d",a);//6
2.前置++(- -)
前置++(- -)先++(- -),后使用
int a = 5;
int b = ++a;
printf("%d",b);//6
printf("%d",a);//6
(4)、(* 、&)的应用
- &取地址
- * 间接访问操作符(解引用操作符)
int a = 5;
printf("%p",&a); //获取变量a的地址---并打印出来
int* pa = &a; //pa用来存放变量a的地址----
//pa就是一个指针变量--类型为int型
*pa = 3; //'*'解引用操作符-间接访问操作符
printf("%d",a); //此时的a的值就会变为3
6.关系操作符
- > 大于
- >= 大于等于
- <小于
- <= 小于等于
- != 不等于 (用于测试"不相等")
- == 用于测试"相等"
在编程的时候一定要分清楚 == 和 = 的区别
7.逻辑操作符
- && 逻辑与
- || 逻辑或
区分逻辑与和按位与 区分逻辑或和按位或
1 & 2--------->0
1 && 2------->1
1 | 2 ------------>3
1 || 2------------>1
int a = 5;
int b = 3;
if(a && b) //此时为1,为真,进入表达式。
{
//表达式;
}
int a = 5;
int b = 0;
if(a && b) //此时为0,为假,不进入表达式。
{
//表达式;
}
int a = 5;
int b = 0;
if(a || b) //此时为1,为真,进入表达式。
{
//表达式;
}
int a = 0;
int b = 0;
if(a || b) //此时为0,为假,不进入表达式。
{
//表达式;
}
接下来看一道题目
#include<stdio.h>
int main()
{
int i = 0,a = 0,b = 2,c = 3,d = 4;
i = a++ && ++b && d++;
printf("a = %d\nb = %d\nc = %d\nd = %d\n",a,b,c,d);
//a = 1 b = 2 c = 3 d = 4
return 0;
}
i = a++ && ++b && d++;
在计算的时候第一步已经为 0 && ++b && d++; ,已经判断为假,后面的就不需要再计算,即结尾a++一下。
如果改一下条件
int i = 0,a = 1,b = 2,c = 3,d = 4;
i = a++ || ++b || d++;
printf("a = %d\nb = %d\nc = %d\nd = %d\n",a,b,c,d);
//a = 2 b = 2 c = 3 d = 4
在计算的时候第一步已经为 1 || ++b || d++;,已经判断为真,后面的就不需要再计算,即结尾a++一下。
8.条件操作符
条件操作符也叫三目操作符
int a = 5;
int b = 3;
if(a > 3)
b = 1;
else
b = -1;
// 等价于下面的代码
int a = 5;
int b = 3;
b = (a > 3 ? 1:-1);
9.逗号表达式
逗号表达式,就是用逗号隔开的多个表达式。逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
接下来看两个例子
int a = 3;
int b = 5;
int c = 0;
int d = (c = 5,a = c + 3,b = a - 4,c += 5);
printf("%d",c); // 10
#include<stdio.h>
int main()
{
int arr[] = {1,2,(3,4),5};
// 数组元素中(3,4)其实就是逗号表达式
//根据逗号表达式的原理可得 arr 中的元素为:{1,2,4,5}
printf("%d",sizeof(arr));// 16
return 0;
}
10.下标引用,函数调用和结构成员
1. [ ]下标引用操作符
操作数:一个数组名 + 一个索引值
int arr[10] = {0,1,2,3,4,5,6,7,8,9,10};
printf("%d",arr[5]); // []---就是下标引用操作符
// 操作数 arr , 5
2.函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
int add(int a,int b)
{
return a + b;
}
int main()
{
int a = 3;
int b = 5;
int ret = add(a,b);// ()-----括号就是函数操作数
// add--第一个参数,a,b------剩余的操作数
return 0;
}
3.访问结构的成员
- .结构体.成员名
- ->结构体指针->成员名
#include<stdio.h>
struct book
{
char name[20];
char id[20];
int price;
};
int main()
{
int num = 10;
struct book b = {"C++","C2022_06_18",13};
// . -------操作符
printf("%s\n",b.name);
printf("%s\n",b.id);
printf("%d\n",b.price);
return 0;
}
#include<stdio.h>
struct book
{
char name[20];
char id[20];
int price;
};
int main()
{
int num = 10;
struct book b = {"C++","C2022_06_18",13};
struct book* pb = &b;
// .--------->操作符 解引用指针访问成员变量
printf("%s\n",(*pb).name);
printf("%s\n",(*pb).id);
printf("%d\n",(*pb).price);
->-------操作符
printf("%s\n",pb->name);
printf("%s\n",pb->id);
printf("%d\n",pb->price);
return 0;
}