- +
- -
- *
- /
- % 浮点型运算不支持取模运算
-
整数在内存中以补码的方式存在
- 正数的补码是源码
- 负数的补码是源码的反码+1
-
>>
-
算术右移
- 右边丢弃,左边补原符号位
- 无符号类型右移右移都是“逻辑移位”
有符号类型右移为“逻辑移位”右移为“算术移位”
-
逻辑右移
- 右边丢弃,左边补0
-
-
<<
-
左移
- 左边丢弃(符号位不变),右边补0
-
-
&
-
位与运算(按位与)
- 整型二进制位相同(1和1)则取1,否则取0
-
-
|
-
位或运算(按位或)
-
整型二进制位相同或不同(1和1或1和0或0和1)取1,否则取0
-
-2 | 1
1000 0000 0000 0000 0000 0000 0000 0010 -2
1111 1111 1111 1111 1111 1111 1111 1101 -2反码
1111 1111 1111 1111 1111 1111 1111 1110 -2补码0000 0000 0000 0000 0000 0000 0000 0001 1 源码
1111 1111 1111 1111 1111 1111 1111 1110 -2 补码1111 1111 1111 1111 1111 1111 1111 1111 | (补码)
1000 0000 0000 0000 0000 0000 0000 0001 源码
-
-
-
-
^
-
位异或运算(按位异或)
- 整型二进制位不同(1和0或0和1)取1,否则取0
-
-
例题
- 例题1:不创建临时变量交换a、b两值
- 解题1
//不创建临时变量交换a、b的值
int a = 3;
int b = 5;
printf("a = %d,b = %d", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("a = %d,b = %d",a ,b);
/*--------------------------------------------*/
- 解题2(优化解题一)
//不创建临时变量交换a、b的值
int a = 3;
int b = 5;
printf("a = %d,b = %d", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d,b = %d",a ,b);
例题2:求一个整数在内存中1的个数。
- 解题一
int num = 0;
scanf("%d",&num);
int count = 0;
while (num){
if (num % 2 == 1){
count++;
}
num /= 2;
}
printf("%d", count);
/*--------------------------------------------*/
- 解题2(优化解题一)
//求一个整数在内存中1的个数。
int num = 0;
scanf("%d",&num);
int count = 0;
for (int i = 0; i < 32; i++){
if (1 == ((num >> i) & 1)){
count++;
}
}
printf("%d", count);
/*--------------------------------------------*/
- 解题3(最优)
//求数字在内存中1的个数。
int input = 0;
int count = 0;
scanf("%d",&input);
//18
//10010 n
//10001 n-1
//10000 n=n&(n-1)
//01111 n-1
//00000 n=n&(n-1)
//每次n&(n-1)都会将最右边的一个1磨掉。
while (input){
input = input & (input - 1);
count++;
}
printf("%d",count);
例题3:整数在内存中求两个数之间有多少位不同
- 解题1
//整数在内存中求两个数之间有多少位不同
int m = 0;
int n = 0;
scanf("%d %d",&m,&n);
int count = 0;
int num = m^n;
while (num){
num = num&(num - 1);
count++;
}
printf("%d",count);
赋值 *** 作符
- 变量名 = 值
-
只有一个 *** 作数
-
!
- 逻辑取反
-
+
-
-
-
&
- 取地址 *** 作符
-
++ 自增
- ++a
- a++
-
- - 自减
- \ - -a
- a- -
-
*
- 间接访问 *** 作符(解引用)
-
~
-
按位取反
- 例题一:
//按位取反;
//将内存中的1011中的0变为1
int a = 11;
a = a | (1 << 2);
printf("%d",a);
//将a变为原来的1011
a = a & ~(1 << 2);
printf("%d", a);
- 例题一:
-
-
(类型)
- 强制类型转换
-
sizeof
-
计算变量在内存中所占的字节数
-
sizeof 求数组的类型大小
- sizeof(int [10]) 其结果为40.
注意:
-
-
shor s = 0;
int a = 2;
printf("%d\n",sizeof((s = a +5)));
printf("%d",s);
其结果为2 0; 这是因为sizeof的表达式语句是不参与运算的。
例题
sizeof的结果和负数比较
例题一:
//10000000 00000000 00000000 00000001 -1源码
//11111111 11111111 11111111 11111110 -1补码
//11111111 11111111 11111111 11111111 -1补码
//11111111 11111111 11111111 11111111 (符号整型)-1
//-1转换为无符号整型,最高位的1不再是符号位,而是数据位
int a = -1;
if (a > sizeof(a)){
printf(">");
}
if (a < sizeof(a)){
printf("<");
}
关系 *** 作符
- >
- <
- >=
- <=
- !=
- ==
-
&&
-
逻辑与
- 左边如果为假,则右边的不再计算。
- 左边如果为假,则右边的不再计算。
-
-
||
-
逻辑或
- 左边如果为真,则右边的不再计算。
- 左边如果为真,则右边的不再计算。
-
- 又名三目运算
- exp1 ? exp2 : exp3
- exp1 , exp2 , exp3 , …
- 由左向右依次执行,最后一个表达式内容为整个表达式结果
- [] 下标引用 *** 作符
- () 函数调用 *** 作符
- " . " 结构体变量名.成员名
- “->” 结构体指针变量名->成员名
-
表达式求值的顺序部分是由 *** 作符的优先级和结核性决定的。
同时,有些表达式的 *** 作数在求值的过程中需要转换成其他数据类型。 -
隐式类型转换
-
C的整型算数运算总是至少以缺省类型的精度来进行的
-
整型提升
-
为了获得这精度,表达式中的字符和短整型 *** 作数在使用之前被转换为普通类型,这种转换被称为整型提升。
-
如何提升
- 按照数据类型的符号来提升的(除值外,其他值补符号位值)
-
何时需要整型提升
- 在进行short/char类型进行算术运算时,先进行整型提升,再进行算术运算。
- 在进行short/char类型进行算术运算时,先进行整型提升,再进行算术运算。
-
意义
- 表达式的整形运算要在CPU的相应运算器件内执行,CPU内整形运算器(ALU)的 *** 作数的字节长度一般就是int的字节长度,同时也是CPU通用寄存器的长度。
- 因此,即两个char类型相加,在CPU执行时实际上也要先转换CPU内整型 *** 作数的标准长度
- 通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。
所以,表达式中各种长度可能小于int长度的整型值,都必须转为int或unsigned int,然后才能送入CPU去执行运算
- 表达式的整形运算要在CPU的相应运算器件内执行,CPU内整形运算器(ALU)的 *** 作数的字节长度一般就是int的字节长度,同时也是CPU通用寄存器的长度。
-
例题:
- 例题1
-
-
//整型提升例题
//00000011 -(char类型) a
char a = 3;
//01111111
char b = 127;
// a + b 先将a 和 b转换成int型
//00000000 00000000 00000000 00000011 -(int类型) a
//00000000 00000000 00000000 01111111 -(int类型) b
//00000000 00000000 00000000 10000010 -(int类型) a+b
//10000010 -(char类型) c
char c = a + b;
//以十进制的方式输出字符类型的c。
需要整型提升。
//10000010 因为符号位为1,所以按照符号位填充
//11111111 11111111 11111111 10000010 -(int 类型) c --补码
//11111111 11111111 11111111 10000001 -(int 类型) c --反码 补码-1是反码 反码+1是补码
//10000000 00000000 00000000 01111110 -(int 类型) c --源码
// -126 c
printf("%d" , c);
- 例题2
// 10110110 -a
//11111111 11111111 11111111 10110110 int a 整形提升(补码)
//10000000 00000000 00000000 01001010 a -32694 (源码)
char a = 0xb6;
//10110110 00000000 -0xb600
//00000000 00000000 10110110 00000000 int
//10110110 00000000 -short b
//11111111 11111111 10110110 00000000 -b 整形提升(补码)
//11111111 11111111 10110101 11111111 -b 整形提升(反码)
//10000000 00000000 01001010 00000000 -b 源码
short b = 0xb600;
//
//10110110 00000000 00000000 00000000 -0xb6000000
int c = 0xb6000000;
//
if (a == 0xb6){
printf("c");
}
if (b == 0xb600){
printf("b");
}
if (c == 0xb6000000){
printf("c");
}
- (char)((char)127+(char)10) = -124
(int)((char)127+(char)10) = 132
-
算数转换
- long double
double
unsigned long int
long int
unsigned int
int
依次向上转换
- long double
- 复杂表达式的求值有三个影响的因素
- ①: *** 作符的优先级
- ②: *** 作符的结核性
- ③:是否控制求值顺序
- 两个相邻的 *** 作符限先执行哪个?取决于他们的优先级。
如果两者的优先级相同,取决于他们的结合性。*** 作符优先级。
-
ab +cd + e*f
- 该表达式只能保证的运算比+的运算提前,但不能保证运算顺序唯一
顺序一:
ab
cd
ab + cd
ef
ab + cd + ef
顺序二:
ab
cd
ef
ab + cd + e*f
- 该表达式只能保证的运算比+的运算提前,但不能保证运算顺序唯一
-
c + --c
- 该表达式只能保证–c在+运算符之前。
但并不能保证c的值是–c计算过后还是之前
- 该表达式只能保证–c在+运算符之前。
int main(){
int i = 10;
i = i-- - --i *(i = -3) * i++ + ++i;
}
printf("%d",i);
该表达式在不同的编译器中有不同的结果。
int fun(){
static int num = 1;
return ++num;
}
int main(){
int answer;
answer = fun() - fun() * fun();
printf("%d",answer);
return 0;
}
表达式不能确定main中调用fun是第几次调用的fun函数,在本电脑的运行结果是-10
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)