C語言入門Part8--操作符篇

C語言入門Part8–操作符篇

關鍵字: 各種操作符的介紹, 表達式求值(整型提升,算術轉換)

操作符

算數操作符

算數操作符包含+ - * / %,主要分析 / 和%

/ 除法運算符
printf("%f\n", 5 / 2);//結果爲0.000000
printf("%d\n", 5 / 2);//結果爲2
printf("%f\n", (flout)5 / 2);//結果爲2.500000
printf("%f\n", 5 / (flout)2);//結果爲2.500000
printf("%f\n", (flout)(5 / 2));//結果爲2.000000
% 求模運算符

對應的兩個操作數都必須是整型,不能是浮點數

       printf("%d\n", 10%3);//1

       printf("%d\n", -10 % 3);//-1

       printf("%d\n", 10 % -3);//1

       printf("%d\n", -10 % -3);//-1
% / 總結
  1. 除了 % 操作符之外,其他的幾個操作符可以作用於整數和浮點數。
  2. 對於 / 操作符如果兩個操作數都爲整數,執行整數除法。只要有浮點數執行的就是浮點數除法。
  3. % 操作符的兩個操作數必須爲整數。返回的是整除之後的餘數。
移位操作符

移位操作符包括左移<<,右移>>

  • 對正數而言左移相當於乘法,右移相當於除法
    11
    0000 1011
    左移
    11<<1
    0001 0110 , 22 , 11* 2^1
    11<<2
    0010 1100 , 44 , 11 * 2^2
    右移
    11>>1
    0000 0101 , 5
    11>>2
    0000 0010 , 2
    跟負數無關
    -1 1111 1111
    -1>>1 1111 1111
  • 計算機中位運算速度遠大於+ - * /
位操作符
  • &按位與
    11 0000 1011
    13 0000 1101
    ret 0000 1001
  • |按位或
    11 0000 1011
    13 0000 1101
    ret 0000 1111
  • ^按位異或 不一樣的時候進行或運算,一樣的時候取0
    11 0000 1011
    13 0000 1101
    ret 0000 0110
  • 連續的數字異或可以消除重複
    A^A = 0
    (AA)B(CC) = B
位操作符的應用實例

實例一:不使用(a + b) / 2這種方式,求兩個數的平均值。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int add(int m, int n)//實現兩數的相加
{
	int ret = m ^ n;//1,0或0,1相加還爲1
	int flag = m & n;//flag爲進位標誌  1,1相加會有進位
	while (flag != 0)//若flag不爲0,則說明有進位  flag左移一位將進的1和ret再進行位運算,循環值無進位爲止
	{
		flag = flag << 1;
		ret = ret ^ flag;
		flag = ret & flag;
	}
	return ret;
}
int div(int a, int b)//實現兩數的平均值計算
{
	int ret;
	int m = ((a^b)>>1);//0,1或1,0相加求平均值時直接右移一位(二進制中右移一位相當於除以2)
	int n = a&b;//1,1相加求平均值還是原位放1,不用移位
	ret=add(m, n);//所以m+n就是求a,b平均值
	return ret;
}
int main()
{
	int a = 100;
	int b = 20;
	printf("a,b平均值爲%d\n",div(a, b));
	return 0;
}

實例二:編程實現:一組數據中只有一個數字出現了一次。
其他所有數字都是成對出現的。請找出這個數字。

//用位運算求非成對出現的數字
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int arr[5] = {1,2,3,2,1};
	int len = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 1; i < len; i++)
	{
		arr[0] = arr[0] ^ arr[i];//連續的異或可以消除重複的元素 a^b^a=b  因爲a^a=0,0^b=b
	}
	printf("只出現了一次的數字是%d\n", arr[0]);
	return 0;
}

實例三:求二進制1的個數

int NumberOf1(unsigned int num)

{

       int count = 0;

       while (num != 0)

       {

              if ((num & 1) != 0)

              {

                      count++;

              }

              num=num >> 1;

       }

       return count;

}

int NumberOf1(int num)

{

       int count = 0;

       while ( num!= 0)

       {

                      count++;

                      num = (num & (num - 1));

       }

       return count;

}
賦值操作符 =

還有些符合賦值操作符,如+=,-=,*=,/=,%=,>>=,<<=,
&=,|=,^=

單目操作符
! 邏輯反操作
- 負值
+ 正值
& 取地址
sizeof 操作數類型長度(以字節爲單位)
~ 對一個數二進制按位取反
前置後置減減
++ 前置後置加加
* 間接訪問操作符(解引用操作符)
(類型) 類型強制轉換
關係操作符

<,>,>=,<=,==,!=
注意不要把 == 和 =混淆

邏輯操作符

&& 邏輯與 也稱短路與
|| 邏輯或 也稱短路或
注意

  • 表達式1&&表達式2
    兩表達式都爲真才爲真,表達式1爲真表達式2才執行,若表達式1爲假,則表達式2不執行
  • 表達式1 || 表達式2
    若表達式1爲真,則後面不再執行,表達式1爲假時,才執行表達式2
#include <stdio.h>
int main()
{
    int i = 0,a=0,b=2,c =3,d=4;
    i = a++ && ++b && d++;//最終執行結果 1 2 3 4
    //i = a++||++b||d++;//最終執行結果1 3 3 4
    printf("%d %d %d %d\n", a, b, c, d);
    return 0; 
}

注意“=”是賦值符號,“==”判斷相等,所以 i = a++ 爲假, i = a++ && ++b && d++;表達式1爲假後面不執行i = a++||++b||d++;表達式1爲假,執行++b,不爲零所以表達式2爲真,表達式3不執行

條件操作符

exp1 ? exp2 : exp3
表達式1是否爲真,爲真返回表達式2,假返回表達式3
應用:不能使用if for 大於 等於等語句,比較兩個數的大小。大於返回1 小於返回-1 等於返回0

int Max(int a,int b)
{
	//return a > b ? a : b;//不能用<,>所以繼續轉變
	return (a-b)>>31 ? -1 : (a-b ? 1 : 0);//a,b都爲int類型,(a-b)>>31判斷符號位,爲1(即爲負數),說明a<b,返回-1;爲0則說明a>=b,所以要繼續判斷a-b的值,不爲0(a>b)返回1,爲0(a=b)返回0
}
逗號表達式

逗號表達式每一個都要執行,但以最後一個表達式結果作爲最終結果

下標引用、函數調用和結構成員
  • 下標引用[] 和 函數調用()常用就不再贅述
  • 訪問一個結構的成員
    .結構體.成員名
    ->結構體指針->成員名
struct Student
{
    char name[10];
    int age;
}stu={"caocao",99};//stu是一個全局變量
//結構體和數組都屬於聚合類型 變量一旦定義,不可改變,整體初始化只有一次機會,所以不推薦定義stu

或
struct Student
{
    char name[10];
    int age;
};
在main函數中
struct Student stu2={"caocao",99};//這樣的話後續改年齡或者其他信息就可以直接改
stu2.age=199;//修改年齡

或者
struct Student *pstu=NULL;
pstu->   //->指向符

表達式求值

  • CPU運算的時候都是4個字節4個字節操作的 所以CPU運算的時候會進行整型提升(即表達式中各種長度小於四個字節的類型都要先轉換爲int類型或unsigned int類型)
  • 整型提升無論正負高位都補符號位
    無符號數高位補0

隱形整型提升例題

char a=0xb6;
short b=0xb600;
int c=0xb6000000;
if(a==0xb6)
	printf("a");//a要進行整型提升,提升後是負數
if(b==0xb600)
	printf("b");//b要進行整型提升,提升後是負數
if(c==0xb6000000)
	printf("c");//c不需要整型提升,所以結果爲真,打印c
算術轉換 儘可能轉換爲當前表達式中最大的類型

long double
double
float
unsigned long int
long int
unsigned int
int
如果某個操作數的類型在上面這個列表中排名較低,那麼首先要轉換爲另外一個操作數的類型後執行運算。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章