詳解C語言中的運算符與表達式

運算符與表達式

什麼是運算符?這裏舉一個例子:
int x,y		//這是聲明兩個變量

x+y  x-y  x==y x=y
上面的“+、-、==、=”就是運算符,還有很多其他的運算符,下面我們會一一介紹。

什麼是表達式:
(x+y)*(x-y)
這就是一個簡單的表達式,無論這個表達式多麼複雜,他最後都是計算出一個結果。

不同類型表達式的計算

例如:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	char x = 1;			//把1賦給char類型的x
	
	short y = 3;		//把3賦給short類型的y

	int z = x+y;		//把x+y返回到int類型的z裏
	printf("%d\n",z);	//以十進制輸出結果到控制檯
	
	return;				//程序結束
}

這裏是兩個變量x,y外加一個返回值z,它們分別是三個類型:char、short、int,那麼他們是怎麼運算的,我們直接去反彙編看一下就行了:
在這裏插入圖片描述
這裏可以看到,程序把x的值存到了eax中,把y的值存到了ecx中,這兩個寄存器都是四個字節的,也就是說,在進行相加之前先轉換成了int類型,那麼int類型又是四個字節,也就是先統一類型,再進行計算,這裏統一類型是有先後級的。

	char  <  short  <  int  <  float  <  double 

這裏總結一下:

  • char類型跟short類型運算,最後都會轉爲int類型。
  • 計算最終結果的類型由表達式中數據寬度最大的那個變量決定。

常見的運算符

算術運算符
+  -  *  /  %  ++  --
加減乘除、取餘、自加、自減

這裏我們主要說一下這個++、–,先上一段代碼:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int x = 1;			//把1賦值給int類型的x裏

	x++;				//在當前x的值的基礎上加1	

	printf("%d\n",x);	//以十進制輸出結果到控制檯
	
	return;				//程序結束
}

運行結果:
在這裏插入圖片描述
那麼++是自加1,–自然就是減1了:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int x = 1;			//把1賦值給int類型的x裏

	x--;				//在當前x的值的基礎上減1	

	printf("%d\n",x);	//以十進制輸出結果到控制檯
	
	return;				//程序結束
}

運行結果:
在這裏插入圖片描述
這個 ++與–可以放在變量前與變量後,放前放後計算出來的結果都是一樣的,但是執行順序有所不同:

	++在前,先自加在進行計算。
	++在後,先進行計算再自加。

改一下代碼:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int x = 1;			//把1賦值給int類型的x裏

	x++;				//x自加1
	
	int y = x;			//把x的值賦給y
	
	printf("%d\n",y);	//輸出結果到控制檯

	return;				//程序結束
}

運行結果:
在這裏插入圖片描述
反彙編看一下是怎麼傳值的:
在這裏插入圖片描述
先看這兩行代碼:

int x = 1;
x++;

這是它的彙編指令:

mov         dword ptr [ebp-4],1
mov         eax,dword ptr [ebp-4]
add         eax,1
mov         dword ptr [ebp-4],eax

先把1賦給ebp-4,再把ebp-4賦給eax,隨後eax再加1,再把1賦值給ebp-4,這一波操作之後x的值就是2了。

接着是這兩行代碼:

int y = x;
printf("%d\n",y);

這裏把2又賦值給了eax,接着把eax賦給ebp+8,接着又把ebp-8賦給了eax,然後eax壓棧,輸出結果。

mov         eax,dword ptr [ebp-4]
mov         dword ptr [ebp-8],eax
mov         eax,dword ptr [ebp-8]
push        eax
push        offset string "%d\n" (00422fa4)
call        printf (00401
090)
add         esp,8

再來看看++在前會是什麼樣的結果:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int x = 1;			//把1賦值給int類型的x裏
	
	printf("%d\n",++x);	//進行自加然後輸出結果到控制檯

	return;				//程序結束
}

反彙編:
在這裏插入圖片描述
這裏可以清楚的看到,程序是先進行了自加,在計算的結果,然後輸出,這就是++在前與在後的區別,–同理。

關係運算符
<  <= >  >= !=  ==
小於、小於等於、大於、大於等於、等於、不等於
關係運算符的值只能是0和1
關係運算符的值爲真時,結果爲1
關係運算符的值爲假時,結果爲0

例子:

#include <stdio.h>			//頭文件

void main()					//程序入口
{
	int a = 10;				//賦值

	int b = 20;			

	int c = a<=b;			//把a<=b的結果返回給c
	
	if(a<=b)					//進行判斷
	{
		printf("正確!\n");	//輸出判斷結果
	}
	else					//否則輸出另一種結果
		printf("錯誤!\n");
	return;					//程序結束
}

看一下運行結果:
在這裏插入圖片描述
爲什麼說結果只有0和1呢?下個斷點看一下C裏的值就知道了:
在這裏插入圖片描述
如果正確就是1,跟我們程序運行後的結果一致(結果爲真)。

邏輯運算符
&&  ||  !
與、或、非
x>y && x<z			只有一個結果
x>y || x<z			只有一個結果

例子:

#include <stdio.h>			//頭文件

void main()					//程序入口
{
	int x = 10;				//賦值

	int y = 20;			

	int z = 30;			
	
	int r = x>y && x<z;		//進行與運算,兩數相與,同真則真
	
	return;					//程序結束
}

我們去反彙編看一下r的值是多少:
在這裏插入圖片描述
值爲0,很明顯這是正確的。

位運算符
<<  >>  ~  |  ^  &
左移、右移、非、邏輯或、異或、邏輯與

例子:

x = 1
y = 2

//與運算,相對應的位都爲1的時候,結果才爲1
0000 0001
0000 0010 &
-----------
0000 0000

//或運算,相對應的位只要有一個爲1,結果就爲1
0000 0001
0000 0010 |
-----------
0000 0011

//異或運算,只有兩個位不一樣的時候,結果爲1,反之爲0
0000 0001
0000 0010 ^
-----------
0000 0011

//非運算,取反即可
0000 0001 ~
-----------
1111 1110

用程序驗證一下:

#include <stdio.h>					//頭文件

void main()							//程序入口
{
	int x = 1;						//賦值
	int y = 2;

	printf("與運算:%d\n",x&y);		//輸出相對應的結果
	printf("或運算:%d\n",x|y);
	printf("異或運算:%d\n",x^y);
	printf("非運算:%d\n",~x);
	
	return;							//程序結束
}

運行結果:
在這裏插入圖片描述

賦值運算符
=   拓展賦值

例子:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int z = 1;			//把1賦值給z
	
	z += 2;				//相當於 int z = z+2;

	printf("%d\n",z)	//輸出結果

	return;				//程序結束
}

運行結果:
在這裏插入圖片描述

運算符的優先級

這裏的優先級跟小學數學一樣,先算乘除,再算加減,有括號先算括號裏的。

例子:

#include <stdio.h>		//頭文件

void main()				//程序入口
{
	int x;				//聲明變量
	x = 2+3*4-8/2		//賦值
	
	printf("%d\n",x);	//輸出結果
	return;				//程序結束
}

運行結果:
在這裏插入圖片描述

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