练习开胃菜
曾经有一道面试题,要求不能创建临时变量(第三个变量),实现两个数的交换。
这道题如果没有前半句的修饰,就只是简单的一道基础题。
法一:
#include <stdio.h>
int main()
{
int a = 0;
int b = 10;
printf("交换前:a=%d,b=%d\n", a, b);
int tmp = a;
a = b;
b = tmp;
printf("交换后:a=%d,b=%d\n", a, b);
return 0;
}
但是如果加上了前半句的修饰,就需要更换思路了。
法二:
#include <stdio.h>
int main()
{
int a = 0;
int b = 10;
printf("交换前:a=%2d,b=%2d\n", a, b);
a = a + b;
b = a - b; //a + b - b = a
a = a - b; //a + b - a = b
printf("交换后:a=%2d,b=%2d\n", a, b);
return 0;
}
第二种方法比第一种方法更考验思维,但是中方法也有弊端,如果a和b两个数无限接近计算机能够储存的最大值,那结果将不再准确。
法三:
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a ^ b; //a 变成了 a^b
b = a ^ b; //a ^ b ^ b = a 相同为0,b变成了a
a = a ^ b; //a ^ b ^ a = b
printf("a = %d b = %d\n", a, b);
return 0;
}
这就是我想讲述的重点:^ 按位异或操作符,二进制位相同为0,相异为1.
技巧1:a ^ 0 = a;
技巧2:a ^ a = 0;
练习1:
#include <stdio.h>
int main()
{
int num = 10;
int count= 0;//计数
while(num)
{
if(num%2 == 1)
count++;
num = num/2;
}
printf("⼆进制中1的个数 = %d\n", count);
return 0;
}
这种方法不能计算负数,所以引入下面的方法
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
for(i=0; i<32; i++)
{
if( num & (1 << i) )
count++;
}
printf("⼆进制中1的个数 = %d\n",count);
return 0;
}
//优化版
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
while(num)
{
count++;
num = num&(num-1);
}
printf("⼆进制中1的个数 = %d\n",count);
return 0;
}
优化版的方法是很难想到的,所以我们要多见,多去思考别人的代码,这样有助于我们的提升。
练习2:
⼆进制位置0或者置1 ,编写代码将13⼆进制序列的第5位修改为1,然后再改回0。
13 的 2 进制序列: 00000000000000000000000000001101将第 5 位置为 1 后: 00000000000000000000000000011101将第 5 位再置为 0 : 00000000000000000000000000001101
#include <stdio.h>
int main()
{
int a = 13;
a = a | (1<<4);
printf("a = %d\n", a);
a = a & ~(1<<4);
printf("a = %d\n", a);
return 0;
}
这里巧妙运用了位操作符,各位可以总结一下。
问题表达式举例
1、a*b + c*d + e*f
// 表达式的求值部分由操作符的优先级决定。表达式1在计算的时候,由于 * ⽐ + 的优先级⾼,只能保证, * 的计算是⽐ + 早,但是优先级并不能决定第三个 * ⽐第⼀个 + 早执⾏,因此表达式的计算顺序不一。
2、 c + --c;
同上,操作符的优先级只能决定⾃减 -- 的运算在 + 的运算的前⾯,但是我们并没有办法得知, + 操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义的。
3、
int i = 10 ;i = i-- - --i * ( i = -3 ) * i++ + ++i;printf ( "i = %d\n" , i);这道题再不同编译器中的结果也不同
4、
int fun() { static int count = 1; return ++count; } int main() { int answer; answer = fun() - fun() * fun(); printf( "%d\n", answer);//输出多少? return 0; }
这个代码实际上有问题,虽然在大多数的编译器上求得的结果都是相同的。
但是上述代码 answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知:先算乘法,再算减法。而函数的调用先后顺序我们无法通过操作符的优先级确定。
5、#include <stdio.h> int main() { int i = 1; int ret = (++i) + (++i) + (++i); printf("%d\n", ret); printf("%d\n", i); return 0; }
这道题在gcc上的编译结果为 10 、4,在vs2022上的编译结果为 12、4.
这段代码中的第⼀个 + 在执⾏的时候,第三个++是否执⾏,这个是不确定的,因为依靠操作符的优先级和结合性是⽆法决定第⼀个 + 和第三个前置 ++ 的先后顺序。所以在不同的编译器上的优先级影响了结果。
结合本期与上期内容,我们要知道:文章来源:https://www.toymoban.com/news/detail-827610.html
文章来源地址https://www.toymoban.com/news/detail-827610.html
到了这里,关于C语言操作符练习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!