c语言_Day20_07_21
1、操作符
1、位操作符
&按位与 |按位或 ^按位异或
位操作符的对象为内存中存储的二进制补码
与找假 ,或找真 ;异或相同为0,不同为1int main()
{
int a = 1;
int b = -1;
printf("%d\n", a & b); // 1
printf("%d\n", a | b); // -1
printf("%d\n", a ^ b); // -2
return 0;
}
面试题:
思路:1. 加减法(可能会溢出)
2. 异或法// 加减法
int main()
{
int a = 10;
int b = 20;
a += b;
b = a - b;
a = a - b;
printf("a = %d b = %d\n", a, b);
return 0;
}
// 异或法
int main()
{
int a = 3;
int b = 5;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
思路:按位与。一个位与1进行按位与后,若该位为1则结果与1相同,反之则相反。对32个位遍历,重复进行上述操作,并且每次循环都对1进行左移操作,可判断32个位的1的个数int main()
{
int num = -1;
int count = 0;
int move = 1;
for (int i = 0; i < 32; i++)
{
if ((num & move) == move)
{
count++;
}
move = move << 1;
}
printf("%d\n", count);
return 0;
}2、赋值操作符
赋值操作符可将右值赋予至左值
连续赋值:c语言支持连续赋值,但并不推荐
复合赋值:
+= -= = /= %=
\>>= <<=
&= |= ^=
左值与右值进行算术操作,得到的结果赋值给左值
3、单目操作符
++ --
! ~
+ -
&
sizeof
(强制类型转换)
只有1个操作数的操作符
!:逻辑取反
&:取地址
*:解引用
sizeof:计算变量或数据类型所占用的内存大小int main()
{
short s = 0;
int a = 10;
printf("%d\n", sizeof(s = a + 5));
printf("%d\n", s);
return 0;
}
sizeof中的表达式不会真实进行计算 ,故s并未被新赋值
~:按位取反
例:对11进行二进制操作,使其变为15(即二进制第3位由0变为1),再变为11int main()
{
int a = 11;
a |= (1 << 2);
printf("%d\n", a);
a &= (~(1 << 2));
printf("%d\n", a);
return 0;
}
练习:void test1(int arr[])
{
printf("%d\n", sizeof(arr)); // 4
printf("%d\n", sizeof(arr[0])); // 4
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch)); // 4
printf("%d\n", sizeof(ch[0])); // 1
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr)); // 40
printf("%d\n", sizeof(ch)); // 10
test1(arr);
test2(ch);
return 0;
}
test函数接收数组的第一个元素的指针,故其大小在32位系统下为4个字节
4、关系操作符
\> < >= <= != ==
5、逻辑操作符
&& ||
短路逻辑:对于逻辑与,若前项为假则不执行后面逻辑;对于逻辑或,若前项为真则不执行后面逻辑int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++; // 短路逻辑
printf("%d %d %d %d\n", a, b, c, d);
return 0;
}
6、条件操作符
exp1 ? exp2 : exp3
exp1为真,则返回exp2,反之返回exp3
7、逗号表达式
exp1, exp2, exp3...
用逗号隔开的多个表达式,从左向右依次执行,整个表达式结果为最后一个表达式
8、下标引用、函数调用和结构成员
[]
()
. ->
下标引用操作符用于访问数组 元素
函数调用操作符用于调用函数
结构成员调用操作符用于调用结构体 的成员:
'. '操作符用于调用结构体对象的成员
'-> '操作符用于调用结构体对象的指针所指向的成员
struct Car
{
int speed;
char name[20];
};
int main()
{
struct Car car = { 60, "X1" };
printf("speed = %d name = %s\n", car.speed, car.name);
printf("speed = %d name = %s\n", (&car)->speed, (&car)->name);
return 0;
}
2、表达式求值
表达式求值需要注意两部分内容:优先级顺序 和类型转换
1、类型转换
整形提升:表达式中的字符和短整形操作数在使用之前被转换为普通整形int main()
{
char a = 3;
char b = 127;
char c = a + b;
printf("%d", c);
return 0;
}
当用a(b)存放3(127)时,a(b)的空间大小为1byte,而3(127)的数据大小为4byte,故数据需要发生截断
字符相加需进行整形提升(按数据类型的符号位进行提升),再计算
将计算结果存放至c中,c的空间大小位1byte,而结果为整形,故数据需要截断
打印整形,故c发生整形提升,得到补码,再转至原码打印
整型提升补充数据规则: