- 不能使用if for > <等语句,比较两个数的大小。大于返回1 小于返回-1 等于返回0
条件操作符
exp1 ? exp2 : exp3
exp1是否为真?为真,exp2;否则exp3
#include<stdio.h>
int Max(int a, int b)
{
//格式:return a > b ? a : b;
return (a - b) >> 31 ? -1 : (a - b ? 1 : 0);
//相减为负数,右移补首符号位'-',则右移32位全是1
//相减为非负数,右移补0
}
int main()
{
printf("%d\n", Max(10, 11)); //-1
printf("%d\n", Max(10, 10)); //0
printf("%d\n", Max(21, 20)); //1
return 0;
}
- 逻辑操作符(短路操作符):
1)逻辑与’&&’
#include<stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++; //第一个为假,后续不执行
printf("a =%d,b =%d,c =%d,d =%d\n", a, b, c, d); //1,2,3,4
return 0;
}
2)逻辑或’||’
#include<stdio.h>
void show1()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || c-- || d++; //a++先运算为0则假,'或'++b先运算为2则真,直接将1赋值给i,后续不执行
printf("show1:i=%d\n", i); //1
printf("验证:a=%d,b=%d,c=%d,d=%d\n", a, b, c, d); //验证结果为:1,3,3,4
printf("\n");
}
void show2()
{
int a = 1;
int b = 0;
int c = 2;
if (a++ || b++ || c++) //'或',a++为真,不执行b++,c++
printf("show2:a=%d,b=%d,c=%d\n", a, b, c); //2,0,2
printf("验证:a=%d,b=%d,c=%d\n", a, b, c); //2,0,2,验证不执行
}
int main()
{
show1();
show2();
return 0;
}
- ‘%’,浮点型判断是否为0,位移运算符
#include<stdio.h>
void show1() //%计算,浮点型转换
{
int a = 2.716;
printf("%d\n", a); //2.7
printf("%d\n", 10 % 3); //1
printf("%d\n", -10 % 3); //-1
printf("%d\n", 10 % -3); //1
printf("%d\n", -10 % -3); //-1
printf("%f\n", 5 / 2); //0.000000
printf("%f\n", (float)5 / 2); //2.500000
printf("%f\n", 5 / (float)2); //2.500000
printf("%f\n", (float)(5 / 2)); //先整型后转换,2.000000
}
void show2() //浮点型判断是否为0
{
float num = 0.0f;
int i = 0;
for (i = 0; i < 10; i++)
num = num + 0.1f;
for (i = 0; i < 10; i++)
num = num - 0.1f;
if (num == 0)
printf("num == 0\n"); //不执行
if (num == 0.000000)
printf("num == 0\n"); //不执行
if (num >= -0.000001 && num <= 0.000001) //判断浮点型(num == 0.0f),不可与0直接比较
printf("num == 0\n");
else
printf("num != 0\n");
}
void show3() //位移运算符
{
char ch1 = 1;
char ch2 = -1;
printf("%d\n", ch1 << -29); //相当于右移29位,即左移3位,8
printf("%d\n", ch2 << -29); //相当于右移29位,即左移3位,-8
}
int main()
{
show1(); //%计算,浮点型转换
show2(); //浮点型判断是否为0
show3(); //位移运算符
return 0;
}
- 按位运算:
(1)按位与:两个数据以二进制形式进行“与”运算;按位与运算符(&)
运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1; 即:两个相应位同时为“1”,则为1,否则为0;
(2)按位或:两个数据以二进制形式进行“或”运算;按位或运算符(|)
运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1; 即:两个相应位只要一个为“1”,则为1,否则为0;
(3)按位异或:两个数据以二进制形式进行“异或”运算。按位异或运算符(^)
运算规则:0^ 0=0; 0^ 1=1; 1^ 0=1; 1^1=0;即:两个相应位只要值不同,则为1,否则为0。
(4)按位取反:一个数据以二进制形式进行“取反”运算。取反运算符(~)
运算规则:~1 = 0; ~0 = 1; 即:对一个二进制数按位取反,将0变1,1变0。
(“~”优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高)
#include<stdio.h>
int main()
{
int a = 99;
//99的二进制形式0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 0011
int b = 5;
//5的二进制形式0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101
int c = -65;
//负数以补码形式存储在计算机,以补码形式参与按位与运算。-65就是65的二进制形式取反(反码)加一(补码)
//-65的二进制补码形式1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1011 1111
int d = 0;
int e = 1;
printf("%d\n", a & b); //即0110 0011 & 0000 0101 = 0000 0001, 结果为1
printf("%d\n", a & c); //即0110 0011 & 1011 1111 = 0010 0011, 结果为35
printf("%d\n", a & d); //清零数据
printf("%d\n", a | b); //即0110 0011 | 0000 0101 = 0110 0111, 结果为103
printf("%d\n", a | c); //即0110 0011 | 1011 1111 = 1111 1111, 结果为-1
printf("%d\n", a | d); //无变化
printf("%d\n", a ^ b); //即0110 0011 ^ 0000 0101 = 0110 0110, 结果为102
printf("%d\n", a ^ c); //即0110 0011 ^ 1011 1111 = 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101 1100, 结果为-36
printf("%d\n", a ^ d); //无变化
printf("~a=%d\n", ~a); //即~0110 0011 = 1001 1100,结果为-100
printf("~b=%d\n", ~b); //即~0000 0101 = 1111 1010,结果为-6
printf("~c=%d\n", ~c); //即~1011 1111 = 0100 0000,结果为64
printf("~d=%d\n", ~d); //即~0000 0000 = 1111 1111,结果为-1
printf("~e=%d\n", ~e); //即~0000 0001 = 1111 1110,结果为-2
printf("a&~1=%d\n", a&~1); //使二进制最后一位变为0,即0110 0011 &~ 0000 0001 = 0110 0010,结果为98
return 0;
}
按位与 特殊用途:取一个数中指定位:
方法:找对应X要取的位,该数的对应位为1,其余位为零,此数与X相与即可得到X中的指定位。
例:取X=1010 1110的低4位,用 X & 0000 1111 = 0000 1110 即可得到;还可用来取X的2、4、6位。
按位或 特殊用途:对一个数据的某些位置1:
方法:找对应X要置1的位,该数的对应位为1,其余位为零。此数与X相或即可使X中的某些位置1。
例:将X=1010 0000的低4位置1 ,用 X | 0000 1111 = 1010 1111即可得到。
“异或运算”的特殊作用:使特定位翻转:
方法:找对应X要翻转的各个位,该数的对应位为1,其余位为零,此数与X对应位异或即可使特定位翻转。
例:X=1010 1110,使X低4位翻转,用X ^ 0000 1111 = 1010 0001即可得到。
附:如果两个不同长度的数据进行位运算时,系统会将二者按右端对齐,然后进行位运算。
例: 在C语言中long型占4个字节,int型占2个字节,如果一个long型数据与一个int型数据进行“与”运算,右端对齐后,左边不足的位依下面三种情况补足,
(1)如果整型数据为正数,左边补16个0。
(2)如果整型数据为负数,左边补16个1。
(3)如果整形数据为无符号数,左边也补16个0。
- 整形提升
C的整型算术运算总是至少以缺省整型类型的精度来进行的,因此在每次运算时要保证足够整形精度。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
int main()
{
char a = 0xb6; short b = 0xb600; int c = 0xb6000000;
if (a == 0xb6)
printf("a"); //不输出
if (b == 0xb600)
printf("b"); //不输出
if (c == 0xb6000000)
printf("c"); //输出c,因为a与b发生了整形提升
return 0;
}
- 算数类型转换
int main()
{
int a = 1;
char b = 'a', c = 'b';
double d;
printf("%d\n", sizeof(!a)); //编译器版本不同答案不同
printf("%d\n", sizeof(c - b)); //不是1,是4
d = c - b;
printf("%d\n", sizeof(d)); //8
return 0;
}