練習開胃菜
曾經(jīng)有一道面試題,要求不能創(chuàng)建臨時變量(第三個變量),實現(xiàn)兩個數(shù)的交換。
這道題如果沒有前半句的修飾,就只是簡單的一道基礎(chǔ)題。
法一:
#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兩個數(shù)無限接近計算機能夠儲存的最大值,那結(jié)果將不再準確。
法三:
#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;//計數(shù)
while(num)
{
if(num%2 == 1)
count++;
num = num/2;
}
printf("?進制中1的個數(shù) = %d\n", count);
return 0;
}
這種方法不能計算負數(shù),所以引入下面的方法
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//計數(shù)
for(i=0; i<32; i++)
{
if( num & (1 << i) )
count++;
}
printf("?進制中1的個數(shù) = %d\n",count);
return 0;
}
//優(yōu)化版
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//計數(shù)
while(num)
{
count++;
num = num&(num-1);
}
printf("?進制中1的個數(shù) = %d\n",count);
return 0;
}
優(yōu)化版的方法是很難想到的,所以我們要多見,多去思考別人的代碼,這樣有助于我們的提升。
練習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;
}
這里巧妙運用了位操作符,各位可以總結(jié)一下。
問題表達式舉例
1、a*b + c*d + e*f
// 表達式的求值部分由操作符的優(yōu)先級決定。????????表達式1在計算的時候,由于 * ? + 的優(yōu)先級?,只能保證, * 的計算是? + 早,但是優(yōu)先級并不能決定第三個 * ?第?個 + 早執(zhí)?,因此表達式的計算順序不一。
2、?c + --c;
????????同上,操作符的優(yōu)先級只能決定?減 -- 的運算在 + 的運算的前?,但是我們并沒有辦法得知, + 操作符的左操作數(shù)的獲取在右操作數(shù)之前還是之后求值,所以結(jié)果是不可預測的,是有歧義的。
3、?
int i = 10 ;i = i-- - --i * ( i = -3 ) * i++ + ++i;printf ( "i = %d\n" , i);這道題再不同編譯器中的結(jié)果也不同![]()
4、
int fun() { static int count = 1; return ++count; } int main() { int answer; answer = fun() - fun() * fun(); printf( "%d\n", answer);//輸出多少? return 0; }
?這個代碼實際上有問題,雖然在大多數(shù)的編譯器上求得的結(jié)果都是相同的。
但是上述代碼 answer = fun() - fun() * fun(); 中我們只能通過操作符的優(yōu)先級得知:先算乘法,再算減法。而函數(shù)的調(diào)用先后順序我們無法通過操作符的優(yōu)先級確定。
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上的編譯結(jié)果為 10 、4,在vs2022上的編譯結(jié)果為 12、4.
????????這段代碼中的第?個 + 在執(zhí)?的時候,第三個++是否執(zhí)?,這個是不確定的,因為依靠操作符的優(yōu)先級和結(jié)合性是?法決定第?個 + 和第三個前置 ++ 的先后順序。所以在不同的編譯器上的優(yōu)先級影響了結(jié)果。
結(jié)合本期與上期內(nèi)容,我們要知道:文章來源:http://www.zghlxwxcb.cn/news/detail-827610.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-827610.html
到了這里,關(guān)于C語言操作符練習的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!