今儿来做一个C语言操作符专栏。
分类:C语言的操作符有如下这些:
- 算术操作符
- 移位操作符
- 赋值操作符
- 单目操作符
- 关系操作符
- 逻辑操作符
- 条件操作符
- 逗号表达式
- 下标引用、函数调用和结构成员
1.算术操作符
+ - * / %
注意:
- %操作符的两个操作数必须为整数,得到的结果为整除之后的余数。其他几个可以用于整数和浮点数。
- /操作符的两个操作数都为整数时执行整数除法。只要有浮点数就执行浮点数除法
2.移位操作符
<<左移操作符,>>右移操作符
使用规则:
- 左移操作符<< 为左边抛弃,右边补0。<<为右边补0,左边抛弃。

- 右移操作符>> 分为两种:1.发生逻辑移位时,左边补0,右边抛弃。2.发生算术移位时,左边补原有值的符号位,右边丢弃。

注意:不要移动负数位。且左移和右移都不改变原有的值。
3.位操作符
按位与&、按位或|、按位异或^
即:按比特位进行比较,如1和2,就应该是0001与0010进行操作比较。
举例说明:
#include<stdio.h>
int main()
{
int num1=1;
int num1=2;
则 num1&num2;
num1|num2;
num1^num2;的值分别为:0,3,3
return 0;
}
延伸:1.不创建第三个变量,实现两个数的交换。核心:a=a^b; b=a ^b;a=a ^b;
2.求一个整数存储在内存中二进制中1的个数。核心:num=num&(num-1)
详情代码见https://github.com/Zhaotiedan/C-Practice.git
4.赋值操作符
int weight =120//定义变量
weight=80//不满意可以自行赋值
复合赋值符:+=、-=、*=、/=、%=、>>=、>>=、&=、!=、^=.
如:int x=10; x+=10;这里的x+=10就相当于x=x+10.
5.单目操作符
!、-、+、&、sizeof、~、--、++、*、(类型)
sizeof:
int main()
{
int a = -10;
int *p = NULL;
a = -a;
p = &a;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(int));
system("pause");
}
值得一提的是,32位平台下任何指针所占大小为4,64位平台下都为8。
sizeof和数组:
#include<stdio.h>
#include<stdlib.h>
void test1(int arr[])
{
printf("%d\n", sizeof(arr));
}
void test2(int arr[])
{
printf("%d\n", sizeof(arr));
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr));//结果为40
printf("%d\n", sizeof(ch));//结果为10
test1(arr);//结果为4
test2(ch);///结果为4
system("pause");
return 0;
}
所以为什么数组作为参数传递后大小会发生改变?因为数组作为函数参数的时候,不会把整个数组地址传递过去,只会传递首元素的地址,所以会发生降维,一位数组会降为指向其内部元素的指针,二维数组会降为一维数组,依次类推。
所以,为了防止出错,arr在哪定义,sizeof就得在哪使用。
++和–:
a++,a–:先使用a值,再自增(自减)。
++a,–a:先自增(自减),再使用a值。
注意:++和–会修改原始的值。
6.关系操作符
>,>=,<=,!=,==
比较简单,注意==与=的区别,不要写错。
7.逻辑操作符
&& 和||
举个例子:
int main()
{
int i = 0;
int a = 0;
int b = 2;
int c = 3;
int d = 4;
i =a++&&++b&&d++;//&&改成||
printf("a=%d b=%d c=%d d=%d", a, b, c, d);// 1,2,3,4(a为0,后面的则都不会执行只进行a自增。)
//1,3,3,4。++b为1,则后面的全不用执行。
system("pause");
return 0;
}
8.条件操作符
exp1?exp2:exp3
9.逗号表达式
从左向右依次执行,整个表达式的结果是最后一个表达式的结果。
10.下标引用,函数调用和结构成员
1.[]下标引用操作符
操作数:一个数组名+一个索引值。
int arr[10];
arr[9]=10;
[]的两个操作数是arr和9.
2.()函数调用操作符
函数名+参数
3.访问一个结构体的成员
结构体的概念:具有相同或不同元素类型的集合,它的初始化与数组一样,能被整体初始化,但不能被整体赋值。
访问格式:
结构体.成员名
结构体指->成员名
#include<stdio.h>
#include<stdlib.h>
struct stu
{
char name[10];
int age;
char sex[5];
double score;
};
int main()
{
struct stu tom = { "tom",19,'m',100 };
printf("%s\n", tom.name);
printf("%d\n", tom.age);
struct stu *p = &tom;
printf("%s\n", p->name);
printf("%d\n", p->age);
system("pause");
return 0;
}
如上代码,两种访问方式都可以。
表达式的求值
1.隐式类型转化
C语言中整型算术运算总是以缺省型类型的精度来进行的,所以为了获得这个精度,表达式中的字符和短整型操作数在使用之前会被转换为普通整型,这个转换过程称为整型提升。
char a,b,c;
...
a=b+c;
b和c的值被提升为普通整型,然后再执行加法运算。即为1字节->4字节。
加法运算完成后,结果将被截断,然后存储在a中。即4字节->1字节。
如何进行整型提升?
概括性的来说,整型提升是按照变量自身的数据类型来决定,无符号填0,有符号填符号位。
//负数的整型提升
char c1=-1;
那么c1的二进制存放形式为:1111 1111,也就是8个比特位。
因为c1为有符号变量,所以char为有符号的char。
所以,在整型提升过程中,高位补充符号位,即为1.
提升之后:为32个比特位
1111 1111 1111 1111 1111 1111 1111 1111
//正数的整型提升
char c2=1;
那么c2的二进制存放形式为:0000 0001,同样为8个比特位。
因为c2为也是有符号变量,所以char为有符号的char。
所以,在整形提升过程中,高位补充符号位,为0.
提升之后:为32个比特位
0000 0000 0000 0000 0000 0000 0000 0001
//无符号的整型提升
unsigned char c3=-1;
则c3存放形式为:1111 1111,8比特位。
这里的c3为无符号变量,char为无符号的char。
所以,在整形提升过程中,高位补0。
提升之后:32个比特位。
0000 0000 0000 0000 0000 0000 1111 1111
整型提升的例子:
1.
int main()
{
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6)
printf("a");
if (b == 0x600)
printf("b");
if (c == 0xb6000000)
printf("c");
system("pause");
return 0;
}
这个结果输出来只有c,因为a,b要整型提升,提升之后变成了负数,所以a0xb6,b0x600的结果为假,但是c是int型的,所以不发生整型提升,所以c==0xb6000000的结果是真。
2.
int main()
{
char c = 1;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(+c));
printf("%u\n", sizeof(!c));
system("pause");
return 0;
}
结果为1 4 1.
c只要参与表达式运算,就会发生整型提升。表达式+c,就会发生整型提升,所以sizeof(+c)就会变成4个字节。
2.算术转换
如果某个操作符的各个操作数属于不同类型,那么除非其中一个操作数转换为另一个操作数类型,否则操作就无法进行。
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。warning:算术转化要合理,不然会有潜在问题。
float f=3.14;
int num =f;//隐式转换,会有精度的丢失
3.操作符的属性
复杂表达式的求值的三个属性:
- 操作符的优先级。(决定整个表达式的运算顺序)
- 操作符的结合性。(决定整个表达式的运算方向)
- 是否控制求值顺序。
两个相邻的操作符先执行哪个?取决于他们优先级。优先级相同则取决于结合性。
操作符的总结暂时先到这里。
1719

被折叠的 条评论
为什么被折叠?



