C语言的操作符

今儿来做一个C语言操作符专栏。
分类:C语言的操作符有如下这些:

  1. 算术操作符
  2. 移位操作符
  3. 赋值操作符
  4. 单目操作符
  5. 关系操作符
  6. 逻辑操作符
  7. 条件操作符
  8. 逗号表达式
  9. 下标引用、函数调用和结构成员

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.操作符的属性
复杂表达式的求值的三个属性:

  • 操作符的优先级。(决定整个表达式的运算顺序)
  • 操作符的结合性。(决定整个表达式的运算方向)
  • 是否控制求值顺序。

两个相邻的操作符先执行哪个?取决于他们优先级。优先级相同则取决于结合性。

操作符的总结暂时先到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值