C 變量
變量其實(shí)只不過(guò)是程序可操作的存儲(chǔ)區(qū)的名稱。C 中每個(gè)變量都有特定的類型,類型決定了變量存儲(chǔ)的大小和布局矾柜,該范圍內(nèi)的值都可以存儲(chǔ)在內(nèi)存中窄刘,運(yùn)算符可應(yīng)用于變量上窥妇。
變量的名稱可以由字母、數(shù)字和下劃線字符組成娩践。它必須以字母或下劃線開頭活翩。大寫字母和小寫字母是不同的,因?yàn)?C 是大小寫敏感的翻伺〔男梗基于前一章講解的基本類型,有以下幾種基本的變量類型:
類型 | 描述 |
---|---|
char | 通常是一個(gè)字節(jié)(八位)吨岭。這是一個(gè)整數(shù)類型拉宗。 |
int | 對(duì)機(jī)器而言,整數(shù)的最自然的大小。 |
float | 單精度浮點(diǎn)值旦事。單精度是這樣的格式魁巩,1位符號(hào),8位指數(shù)姐浮,23位小數(shù)谷遂。 img
|
double | 雙精度浮點(diǎn)值。雙精度是1位符號(hào)卖鲤,11位指數(shù)肾扰,52位小數(shù)。 img
|
void | 表示類型的缺失蛋逾。 |
C 語(yǔ)言也允許定義各種其他類型的變量集晚,比如枚舉、指針换怖、數(shù)組甩恼、結(jié)構(gòu)、共用體等等沉颂,這將會(huì)在后續(xù)的章節(jié)中進(jìn)行講解条摸,本章節(jié)我們先講解基本變量類型。
C 中的變量定義
變量定義就是告訴編譯器在何處創(chuàng)建變量的存儲(chǔ)铸屉,以及如何創(chuàng)建變量的存儲(chǔ)钉蒲。變量定義指定一個(gè)數(shù)據(jù)類型,并包含了該類型的一個(gè)或多個(gè)變量的列表彻坛,如下所示:
type variable_list;
在這里顷啼,type 必須是一個(gè)有效的 C 數(shù)據(jù)類型,可以是 char昌屉、w_char钙蒙、int、float间驮、double 或任何用戶自定義的對(duì)象躬厌,variable_list 可以由一個(gè)或多個(gè)標(biāo)識(shí)符名稱組成,多個(gè)標(biāo)識(shí)符之間用逗號(hào)分隔竞帽。下面列出幾個(gè)有效的聲明:
int i, j, k;
char c, ch;
float f, salary;
double d;
行 int i, j, k; 聲明并定義了變量 i扛施、j 和 k,這指示編譯器創(chuàng)建類型為 int 的名為 i屹篓、j疙渣、k 的變量。
變量可以在聲明的時(shí)候被初始化(指定一個(gè)初始值)堆巧。初始化器由一個(gè)等號(hào)妄荔,后跟一個(gè)常量表達(dá)式組成泼菌,如下所示:
type variable_name = value;
下面列舉幾個(gè)實(shí)例:
extern int d = 3, f = 5; // d 和 f 的聲明與初始化
int d = 3, f = 5; // 定義并初始化 d 和 f
byte z = 22; // 定義并初始化 z
char x = 'x'; // 變量 x 的值為 'x'
不帶初始化的定義:帶有靜態(tài)存儲(chǔ)持續(xù)時(shí)間的變量會(huì)被隱式初始化為 NULL(所有字節(jié)的值都是 0),其他所有變量的初始值是未定義的懦冰。
C 中的變量聲明
變量聲明向編譯器保證變量以指定的類型和名稱存在灶轰,這樣編譯器在不需要知道變量完整細(xì)節(jié)的情況下也能繼續(xù)進(jìn)一步的編譯谣沸。變量聲明只在編譯時(shí)有它的意義刷钢,在程序連接時(shí)編譯器需要實(shí)際的變量聲明。
變量的聲明有兩種情況:
- 1乳附、一種是需要建立存儲(chǔ)空間的内地。例如:int a 在聲明的時(shí)候就已經(jīng)建立了存儲(chǔ)空間。
- 2赋除、另一種是不需要建立存儲(chǔ)空間的阱缓,通過(guò)使用extern關(guān)鍵字聲明變量名而不定義它。 例如:extern int a 其中變量 a 可以在別的文件中定義的举农。
- 除非有extern關(guān)鍵字荆针,否則都是變量的定義。
extern int i; //聲明颁糟,不是定義
int i; //聲明航背,也是定義
實(shí)例
嘗試下面的實(shí)例,其中棱貌,變量在頭部就已經(jīng)被聲明玖媚,但是定義與初始化在主函數(shù)內(nèi):
實(shí)例
#include <stdio.h>
// 變量聲明
extern int a, b;
extern int c;
extern float f;
int main ()
{
/* 變量定義 */
int a, b;
int c;
float f;
/* 初始化 */
a = 10;
b = 20;
c = a + b;
printf("value of c : %d \n", c);
f = 70.0/3.0;
printf("value of f : %f \n", f);
return 0;
}
當(dāng)上面的代碼被編譯和執(zhí)行時(shí),它會(huì)產(chǎn)生下列結(jié)果:
value of c : 30
value of f : 23.333334
C 中的左值(Lvalues)和右值(Rvalues)
C 中有兩種類型的表達(dá)式:
- 左值(lvalue):指向內(nèi)存位置的表達(dá)式被稱為左值(lvalue)表達(dá)式婚脱。左值可以出現(xiàn)在賦值號(hào)的左邊或右邊今魔。
- 右值(rvalue):術(shù)語(yǔ)右值(rvalue)指的是存儲(chǔ)在內(nèi)存中某些地址的數(shù)值。右值是不能對(duì)其進(jìn)行賦值的表達(dá)式障贸,也就是說(shuō)错森,右值可以出現(xiàn)在賦值號(hào)的右邊,但不能出現(xiàn)在賦值號(hào)的左邊篮洁。
變量是左值涩维,因此可以出現(xiàn)在賦值號(hào)的左邊。數(shù)值型的字面值是右值嘀粱,因此不能被賦值激挪,不能出現(xiàn)在賦值號(hào)的左邊。下面是一個(gè)有效的語(yǔ)句:
int g = 20;
但是下面這個(gè)就不是一個(gè)有效的語(yǔ)句锋叨,會(huì)生成編譯時(shí)錯(cuò)誤:
10 = 20;
(左值和右值比較難懂垄分,地址理解左值與右值)
C 常量
常量是固定值,在程序執(zhí)行期間不會(huì)改變娃磺。這些固定的值薄湿,又叫做字面量。
常量可以是任何的基本數(shù)據(jù)類型,比如整數(shù)常量豺瘤、浮點(diǎn)常量吆倦、字符常量,或字符串字面值坐求,也有枚舉常量蚕泽。
常量就像是常規(guī)的變量,只不過(guò)常量的值在定義后不能進(jìn)行修改桥嗤。
整數(shù)常量
整數(shù)常量可以是十進(jìn)制须妻、八進(jìn)制或十六進(jìn)制的常量。前綴指定基數(shù):0x 或 0X 表示十六進(jìn)制泛领,0 表示八進(jìn)制荒吏,不帶前綴則默認(rèn)表示十進(jìn)制。
整數(shù)常量也可以帶一個(gè)后綴渊鞋,后綴是 U 和 L 的組合绰更,U 表示無(wú)符號(hào)整數(shù)(unsigned),L 表示長(zhǎng)整數(shù)(long)锡宋。后綴可以是大寫儡湾,也可以是小寫,U 和 L 的順序任意员辩。
下面列舉幾個(gè)整數(shù)常量的實(shí)例:
212 /* 合法的 */
215u /* 合法的 */
0xFeeL /* 合法的 */
078 /* 非法的:8 不是八進(jìn)制的數(shù)字 */
032UU /* 非法的:不能重復(fù)后綴 */
以下是各種類型的整數(shù)常量的實(shí)例:
85 /* 十進(jìn)制 */
0213 /* 八進(jìn)制 */
0x4b /* 十六進(jìn)制 */
30 /* 整數(shù) */
30u /* 無(wú)符號(hào)整數(shù) */
30l /* 長(zhǎng)整數(shù) */
30ul /* 無(wú)符號(hào)長(zhǎng)整數(shù) */
浮點(diǎn)常量
浮點(diǎn)常量由整數(shù)部分盒粮、小數(shù)點(diǎn)、小數(shù)部分和指數(shù)部分組成奠滑。您可以使用小數(shù)形式或者指數(shù)形式來(lái)表示浮點(diǎn)常量丹皱。
當(dāng)使用小數(shù)形式表示時(shí),必須包含整數(shù)部分宋税、小數(shù)部分摊崭,或同時(shí)包含兩者。當(dāng)使用指數(shù)形式表示時(shí)杰赛, 必須包含小數(shù)點(diǎn)呢簸、指數(shù),或同時(shí)包含兩者乏屯。帶符號(hào)的指數(shù)是用 e 或 E 引入的根时。
下面列舉幾個(gè)浮點(diǎn)常量的實(shí)例:
3.14159 /* 合法的 */
314159E-5L /* 合法的 */
510E /* 非法的:不完整的指數(shù) */
210f /* 非法的:沒(méi)有小數(shù)或指數(shù) */
.e55 /* 非法的:缺少整數(shù)或分?jǐn)?shù) */
字符常量
字符常量是括在單引號(hào)中,例如辰晕,'x' 可以存儲(chǔ)在 char 類型的簡(jiǎn)單變量中蛤迎。
字符常量可以是一個(gè)普通的字符(例如 'x')、一個(gè)轉(zhuǎn)義序列(例如 '\t')含友,或一個(gè)通用的字符(例如 '\u02C0')替裆。
在 C 中校辩,有一些特定的字符,當(dāng)它們前面有反斜杠時(shí)辆童,它們就具有特殊的含義宜咒,被用來(lái)表示如換行符(\n)或制表符(\t)等。下表列出了一些這樣的轉(zhuǎn)義序列碼:
轉(zhuǎn)義序列 | 含義 |
---|---|
\ | \ 字符 |
' | ' 字符 |
" | " 字符 |
? | ? 字符 |
\a | 警報(bào)鈴聲 |
\b | 退格鍵 |
\f | 換頁(yè)符 |
\n | 換行符 |
\r | 回車 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ooo | 一到三位的八進(jìn)制數(shù) |
\xhh . . . | 一個(gè)或多個(gè)數(shù)字的十六進(jìn)制數(shù) |
下面的實(shí)例顯示了一些轉(zhuǎn)義序列字符:
實(shí)例
#include <stdio.h>
int main()
{ printf("Hello\tWorld\n\n");
return 0; }
當(dāng)上面的代碼被編譯和執(zhí)行時(shí)把鉴,它會(huì)產(chǎn)生下列結(jié)果:
Hello World
字符串常量
字符串字面值或常量是括在雙引號(hào) "" 中的故黑。一個(gè)字符串包含類似于字符常量的字符:普通的字符、轉(zhuǎn)義序列和通用的字符纸镊。
您可以使用空格做分隔符倍阐,把一個(gè)很長(zhǎng)的字符串常量進(jìn)行分行。
下面的實(shí)例顯示了一些字符串常量逗威。下面這三種形式所顯示的字符串是相同的。
"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
定義常量
在 C 中岔冀,有兩種簡(jiǎn)單的定義常量的方式:
- 使用 #define 預(yù)處理器凯旭。
- 使用 const 關(guān)鍵字。
#define 預(yù)處理器
下面是使用 #define 預(yù)處理器定義常量的形式:
#define identifier value
具體請(qǐng)看下面的實(shí)例:
#include <stdio.h>
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
int main()
{
int area;
area = LENGTH * WIDTH;
printf("value of area : %d", area);
printf("%c", NEWLINE);
return 0;
}
當(dāng)上面的代碼被編譯和執(zhí)行時(shí)使套,它會(huì)產(chǎn)生下列結(jié)果:
value of area : 50
const 關(guān)鍵字
您可以使用 const 前綴聲明指定類型的常量罐呼,如下所示:
const type variable = value;
具體請(qǐng)看下面的實(shí)例:
實(shí)例
#include <stdio.h>
int main()
{
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE = '\n';
int area;
area = LENGTH * WIDTH;
printf("value of area : %d", area);
printf("%c", NEWLINE);
return 0;
}
當(dāng)上面的代碼被編譯和執(zhí)行時(shí),它會(huì)產(chǎn)生下列結(jié)果:
value of area : 50
請(qǐng)注意侦高,把常量定義為大寫字母形式嫉柴,是一個(gè)很好的編程實(shí)踐。
C 存儲(chǔ)類
存儲(chǔ)類定義 C 程序中變量/函數(shù)的范圍(可見(jiàn)性)和生命周期奉呛。這些說(shuō)明符放置在它們所修飾的類型之前计螺。下面列出 C 程序中可用的存儲(chǔ)類:
- auto
- register
- static
- extern
auto 存儲(chǔ)類
auto 存儲(chǔ)類是所有局部變量默認(rèn)的存儲(chǔ)類。
{
int mount;
auto int month;
}
上面的實(shí)例定義了兩個(gè)帶有相同存儲(chǔ)類的變量瞧壮,auto 只能用在函數(shù)內(nèi)登馒,即 auto 只能修飾局部變量。
register 存儲(chǔ)類
register 存儲(chǔ)類用于定義存儲(chǔ)在寄存器中而不是 RAM 中的局部變量咆槽。這意味著變量的最大尺寸等于寄存器的大谐陆巍(通常是一個(gè)詞),且不能對(duì)它應(yīng)用一元的 '&' 運(yùn)算符(因?yàn)樗鼪](méi)有內(nèi)存位置)秦忿。
{
register int miles;
}
寄存器只用于需要快速訪問(wèn)的變量麦射,比如計(jì)數(shù)器。還應(yīng)注意的是灯谣,定義 'register' 并不意味著變量將被存儲(chǔ)在寄存器中潜秋,它意味著變量可能存儲(chǔ)在寄存器中,這取決于硬件和實(shí)現(xiàn)的限制酬屉。
寄存器的工作方式很簡(jiǎn)單半等,只有兩步:
(1)找到相關(guān)的位揍愁,(2)讀取這些位。
內(nèi)存的工作方式就要復(fù)雜得多:
(1)找到數(shù)據(jù)的指針杀饵。(指針可能存放在寄存器內(nèi)莽囤,所以這一步就已經(jīng)包括寄存器的全部工作了。)
(2)將指針?biāo)屯鶅?nèi)存管理單元(MMU)切距,由MMU將虛擬的內(nèi)存地址翻譯成實(shí)際的物理地址朽缎。
(3)將物理地址送往內(nèi)存控制器(memory controller),由內(nèi)存控制器找出該地址在哪一根內(nèi)存插槽(bank)上谜悟。
(4)確定數(shù)據(jù)在哪一個(gè)內(nèi)存塊(chunk)上话肖,從該塊讀取數(shù)據(jù)。
(5)數(shù)據(jù)先送回內(nèi)存控制器葡幸,再送回CPU最筒,然后開始使用。
static 存儲(chǔ)類
static 存儲(chǔ)類指示編譯器在程序的生命周期內(nèi)保持局部變量的存在蔚叨,而不需要在每次它進(jìn)入和離開作用域時(shí)進(jìn)行創(chuàng)建和銷毀床蜘。因此,使用 static 修飾局部變量可以在函數(shù)調(diào)用之間保持局部變量的值蔑水。
static 修飾符也可以應(yīng)用于全局變量邢锯。當(dāng) static 修飾全局變量時(shí),會(huì)使變量的作用域限制在聲明它的文件內(nèi)搀别。
全局聲明的一個(gè) static 變量或方法可以被任何函數(shù)或方法調(diào)用丹擎,只要這些方法出現(xiàn)在跟 static 變量或方法同一個(gè)文件中。
以下實(shí)例演示了 static 修飾全局變量和局部變量的應(yīng)用:
-
#include <stdio.h> /* 函數(shù)聲明 */ void sum_num(void); static int count=10; /* 全局變量 - static 是默認(rèn)的 */ int main() { while (count--) { sum_num(); } return 0; } void sum_num(void) { /* 'another_count' 是 'sum_num' 的局部變量 - 只初始化一次 - 每次調(diào)用函數(shù) 'sum_num' 'another_count' 值不會(huì)被重置歇父。 */ static int another_count=5; another_count++; printf(" another_count is %d , count is %d\n", another_count, count); }
實(shí)例中 count 作為全局變量可以在函數(shù)內(nèi)使用蒂培,thingy 使用 static 修飾后,不會(huì)再每次調(diào)用時(shí)重置庶骄。
可能您現(xiàn)在還無(wú)法理解這個(gè)實(shí)例毁渗,因?yàn)槲乙呀?jīng)使用了函數(shù)和全局變量,這兩個(gè)概念目前為止還沒(méi)進(jìn)行講解单刁。即使您現(xiàn)在不能完全理解灸异,也沒(méi)有關(guān)系,后續(xù)的章節(jié)我們會(huì)詳細(xì)講解羔飞。當(dāng)上面的代碼被編譯和執(zhí)行時(shí)肺樟,它會(huì)產(chǎn)生下列結(jié)果:
another_count is 6 , count is 9
another_count is 7 , count is 8
another_count is 8 , count is 7
another_count is 9 , count is 6
another_count is 10 , count is 5
another_count is 11 , count is 4
another_count is 12 , count is 3
another_count is 13 , count is 2
another_count is 14 , count is 1
another_count is 15 , count is 0
extern 存儲(chǔ)類
extern 存儲(chǔ)類用于提供一個(gè)全局變量的引用,全局變量對(duì)所有的程序文件都是可見(jiàn)的逻淌。當(dāng)您使用 'extern' 時(shí)么伯,對(duì)于無(wú)法初始化的變量,會(huì)把變量名指向一個(gè)之前定義過(guò)的存儲(chǔ)位置卡儒。
當(dāng)您有多個(gè)文件且定義了一個(gè)可以在其他文件中使用的全局變量或函數(shù)時(shí)田柔,可以在其他文件中使用 extern 來(lái)得到已定義的變量或函數(shù)的引用俐巴。可以這么理解硬爆,extern 是用來(lái)在另一個(gè)文件中聲明一個(gè)全局變量或函數(shù)欣舵。
extern 修飾符通常用于當(dāng)有兩個(gè)或多個(gè)文件共享相同的全局變量或函數(shù)的時(shí)候,如下所示:
第一個(gè)文件:main.c
#include <stdio.h>
int conbas ;
extern void write_extern();
int main()
{
conbas = 20;
write_extern();
}
//
// Created by Lenovo on 2018/12/11.
//
#include <stdio.h>
extern int conbas;
void writen_extern(void) {
printf("conbas is %d\n", conbas);
}
conbas is 20
C 運(yùn)算符
運(yùn)算符是一種告訴編譯器執(zhí)行特定的數(shù)學(xué)或邏輯操作的符號(hào)缀磕。C 語(yǔ)言內(nèi)置了豐富的運(yùn)算符缘圈,并提供了以下類型的運(yùn)算符:
- 算術(shù)運(yùn)算符
- 關(guān)系運(yùn)算符
- 邏輯運(yùn)算符
- 位運(yùn)算符
- 賦值運(yùn)算符
- 雜項(xiàng)運(yùn)算符
本章將逐一介紹算術(shù)運(yùn)算符、關(guān)系運(yùn)算符袜蚕、邏輯運(yùn)算符糟把、位運(yùn)算符、賦值運(yùn)算符和其他運(yùn)算符牲剃。
算術(shù)運(yùn)算符
下表顯示了 C 語(yǔ)言支持的所有算術(shù)運(yùn)算符遣疯。假設(shè)變量 A 的值為 10,變量 B 的值為 20颠黎,則:
運(yùn)算符 | 描述 | 實(shí)例 |
---|---|---|
+ | 把兩個(gè)操作數(shù)相加 | A + B 將得到 30 |
- | 從第一個(gè)操作數(shù)中減去第二個(gè)操作數(shù) | A - B 將得到 -10 |
* | 把兩個(gè)操作數(shù)相乘 | A * B 將得到 200 |
/ | 分子除以分母 | B / A 將得到 2 |
% | 取模運(yùn)算符另锋,整除后的余數(shù) | B % A 將得到 0 |
++ | 自增運(yùn)算符,整數(shù)值增加 1 | A++ 將得到 11 |
-- | 自減運(yùn)算符狭归,整數(shù)值減少 1 | A-- 將得到 9 |
實(shí)例
請(qǐng)看下面的實(shí)例,了解 C 語(yǔ)言中所有可用的算術(shù)運(yùn)算符:
void operator(void) {
int a = 21;
int b = 10;
int c;
c = a + b;
printf("Line 1 - c is %d\n", c);
c = a - b;
printf("Line 2 - c is %d\n", c);
c = a * b;
printf("Line 3 - c is %d\n", c);
c = a / b;
printf("Line 4 - c is %d\n", c);
c = a % b;
printf("Line 5 - c is %d\n", c);
c = a++; // 賦值后再加 1 文判,c 為 21过椎,a 為 22
printf("Line 6 - c is %d\n", c);
c = a--; // 賦值后再減 1 ,c 為 22 戏仓,a 為 21
printf("Line 7 - c is %d\n", c);
}
Line 1 - c is 31
Line 2 - c is 11
Line 3 - c is 210
Line 4 - c is 2
Line 5 - c is 1
Line 6 - c is 21
Line 7 - c is 22
以下實(shí)例演示了 a++ 與 ++a 的區(qū)別:
void before_next(void){
int c;
int a = 10;
c = a++;
printf("a * *\n");
printf("Line 1 - c is %d\n", c );
printf("Line 2 - a is %d\n", a );
a = 10;
c = a--;
printf("Line 3 - c is %d\n", c );
printf("Line 4 - a is %d\n", a );
printf("* * a\n");
a = 10;
c = ++a;
printf("Line 5 - c is %d\n", c );
printf("Line 6 - a is %d\n", a );
a = 10;
c = --a;
printf("Line 7 - c is %d\n", c );
printf("Line 8 - a is %d\n", a );
}
a * *
Line 1 - c is 10
Line 2 - a is 11
Line 3 - c is 10
Line 4 - a is 9
* * a
Line 5 - c is 11
Line 6 - a is 11
Line 7 - c is 9
Line 8 - a is 9
關(guān)系運(yùn)算符
下表顯示了 C 語(yǔ)言支持的所有關(guān)系運(yùn)算符疚宇。假設(shè)變量 A 的值為 10,變量 B 的值為 20赏殃,則:
運(yùn)算符 | 描述 | 實(shí)例 |
---|---|---|
== | 檢查兩個(gè)操作數(shù)的值是否相等敷待,如果相等則條件為真。 | (A == B) 不為真仁热。 |
!= | 檢查兩個(gè)操作數(shù)的值是否相等榜揖,如果不相等則條件為真。 | (A != B) 為真抗蠢。 |
> | 檢查左操作數(shù)的值是否大于右操作數(shù)的值举哟,如果是則條件為真。 | (A > B) 不為真迅矛。 |
< | 檢查左操作數(shù)的值是否小于右操作數(shù)的值妨猩,如果是則條件為真。 | (A < B) 為真秽褒。 |
>= | 檢查左操作數(shù)的值是否大于或等于右操作數(shù)的值壶硅,如果是則條件為真威兜。 | (A >= B) 不為真。 |
<= | 檢查左操作數(shù)的值是否小于或等于右操作數(shù)的值庐椒,如果是則條件為真椒舵。 | (A <= B) 為真。 |
實(shí)例
請(qǐng)看下面的實(shí)例扼睬,了解 C 語(yǔ)言中所有可用的關(guān)系運(yùn)算符:
void relational_operator(void) {
int a = 21;
int b = 10;
int c;
if (a == b) {
printf("Line 1 - a 等于 b\n");
} else {
printf("Line 1 - a 不等于 b\n");
}
if (a < b) {
printf("Line 2 - a 小于 b\n");
} else {
printf("Line 2 - a 不小于 b\n");
}
if (a > b) {
printf("Line 3 - a 大于 b\n");
} else {
printf("Line 3 - a 不大于 b\n");
}
/* 改變 a 和 b 的值 */
a = 5;
b = 20;
if (a <= b) {
printf("Line 4 - a 小于或等于 b\n");
}
if (b >= a) {
printf("Line 5 - b 大于或等于 a\n");
}
}
Line 1 - a 不等于 b
Line 2 - a 不小于 b
Line 3 - a 大于 b
Line 4 - a 小于或等于 b
Line 5 - b 大于或等于 a
邏輯運(yùn)算符
下表顯示了 C 語(yǔ)言支持的所有關(guān)系邏輯運(yùn)算符逮栅。假設(shè)變量 A 的值為 1,變量 B 的值為 0窗宇,則:
運(yùn)算符 | 描述 | 實(shí)例 |
---|---|---|
&& | 稱為邏輯與運(yùn)算符措伐。如果兩個(gè)操作數(shù)都非零,則條件為真军俊。 | (A && B) 為假侥加。 |
|| | 稱為邏輯或運(yùn)算符。如果兩個(gè)操作數(shù)中有任意一個(gè)非零粪躬,則條件為真担败。 | (A || B) 為真。 |
! | 稱為邏輯非運(yùn)算符镰官。用來(lái)逆轉(zhuǎn)操作數(shù)的邏輯狀態(tài)提前。如果條件為真則邏輯非運(yùn)算符將使其為假。 | !(A && B) 為真泳唠。 |
實(shí)例
請(qǐng)看下面的實(shí)例狈网,了解 C 語(yǔ)言中所有可用的邏輯運(yùn)算符:
void logical_operator(void) {
int a = 5;
int b = 20;
int c;
if (a && b) {
printf("Line 1 - 條件為真\n");
}
if (a || b) {
printf("Line 2 - 條件為真\n");
}
/* 改變 a 和 b 的值 */
a = 0;
b = 10;
if (a && b) {
printf("Line 3 - 條件為真\n");
} else {
printf("Line 3 - 條件不為真\n");
}
if (!(a && b)) {
printf("Line 4 - 條件為真\n");
}
}
Line 1 - 條件為真
Line 2 - 條件為真
Line 3 - 條件不為真
Line 4 - 條件為真
位運(yùn)算符
位運(yùn)算符作用于位,并逐位執(zhí)行操作笨腥。&拓哺、 | 和 ^ 的真值表如下所示:
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假設(shè)如果 A = 60,且 B = 13脖母,現(xiàn)在以二進(jìn)制格式表示士鸥,它們?nèi)缦滤荆?/p>
A = 0011 1100
B = 0000 1101
\-----------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
下表顯示了 C 語(yǔ)言支持的位運(yùn)算符。假設(shè)變量 A 的值為 60谆级,變量 B 的值為 13烤礁,則:
運(yùn)算符 | 描述 | 實(shí)例 | ||||
---|---|---|---|---|---|---|
& | 按位與操作,按二進(jìn)制位進(jìn)行"與"運(yùn)算哨苛。運(yùn)算規(guī)則: 0&0=0; 0&1=0; 1&0=0; 1&1=1;
|
(A & B) 將得到 12鸽凶,即為 0000 1100 | ||||
| | 按位或運(yùn)算符,按二進(jìn)制位進(jìn)行"或"運(yùn)算建峭。運(yùn)算規(guī)則: `0 | 0=0; 0 | 1=1; 1 | 0=1; 1 | 1=1;` | (A | B) 將得到 61玻侥,即為 0011 1101 |
^ | 異或運(yùn)算符,按二進(jìn)制位進(jìn)行"異或"運(yùn)算亿蒸。運(yùn)算規(guī)則: 0^0=0; 0^1=1; 1^0=1; 1^1=0;
|
(A ^ B) 將得到 49凑兰,即為 0011 0001 | ||||
~ | 取反運(yùn)算符掌桩,按二進(jìn)制位進(jìn)行"取反"運(yùn)算。運(yùn)算規(guī)則: ~1=0; ~0=1;
|
(~A ) 將得到 -61姑食,即為 1100 0011波岛,一個(gè)有符號(hào)二進(jìn)制數(shù)的補(bǔ)碼形式。 | ||||
<< | 二進(jìn)制左移運(yùn)算符音半。將一個(gè)運(yùn)算對(duì)象的各二進(jìn)制位全部左移若干位(左邊的二進(jìn)制位丟棄则拷,右邊補(bǔ)0)。 | A << 2 將得到 240曹鸠,即為 1111 0000 | ||||
>> | 二進(jìn)制右移運(yùn)算符煌茬。將一個(gè)數(shù)的各二進(jìn)制位全部右移若干位,正數(shù)左補(bǔ)0彻桃,負(fù)數(shù)左補(bǔ)1坛善,右邊丟棄。 | A >> 2 將得到 15邻眷,即為 0000 1111 |
實(shí)例
請(qǐng)看下面的實(shí)例眠屎,了解 C 語(yǔ)言中所有可用的位運(yùn)算符:
void bitwise_operation(void) {
unsigned int a = 60; /* 60 = 0011 1100 */
unsigned int b = 13; /* 13 = 0000 1101 */
int c = 0;
c = a & b; /* 12 = 0000 1100 */
printf("Line 1 - c is %d\n", c);
c = a | b; /* 61 = 0011 1101 */
printf("Line 2 - c is %d\n", c);
c = a ^ b; /* 49 = 0011 0001 */
printf("Line 3 - c is %d\n", c);
c = ~a; /*-61 = 1100 0011 */
printf("Line 4 - c is %d\n", c);
c = a << 2; /* 240 = 1111 0000 */
printf("Line 5 - c is %d\n", c);
c = a >> 2; /* 15 = 0000 1111 */
printf("Line 6 - c is %d\n", c);
}
賦值運(yùn)算符
下表列出了 C 語(yǔ)言支持的賦值運(yùn)算符:
運(yùn)算符 | 描述 | 實(shí)例 |
---|---|---|
= | 簡(jiǎn)單的賦值運(yùn)算符,把右邊操作數(shù)的值賦給左邊操作數(shù) | C = A + B 將把 A + B 的值賦給 C |
+= | 加且賦值運(yùn)算符肆饶,把右邊操作數(shù)加上左邊操作數(shù)的結(jié)果賦值給左邊操作數(shù) | C += A 相當(dāng)于 C = C + A |
-= | 減且賦值運(yùn)算符改衩,把左邊操作數(shù)減去右邊操作數(shù)的結(jié)果賦值給左邊操作數(shù) | C -= A 相當(dāng)于 C = C - A |
*= | 乘且賦值運(yùn)算符,把右邊操作數(shù)乘以左邊操作數(shù)的結(jié)果賦值給左邊操作數(shù) | C *= A 相當(dāng)于 C = C * A |
/= | 除且賦值運(yùn)算符驯镊,把左邊操作數(shù)除以右邊操作數(shù)的結(jié)果賦值給左邊操作數(shù) | C /= A 相當(dāng)于 C = C / A |
%= | 求模且賦值運(yùn)算符燎字,求兩個(gè)操作數(shù)的模賦值給左邊操作數(shù) | C %= A 相當(dāng)于 C = C % A |
<<= | 左移且賦值運(yùn)算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且賦值運(yùn)算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位與且賦值運(yùn)算符 | C &= 2 等同于 C = C & 2 |
^= | 按位異或且賦值運(yùn)算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且賦值運(yùn)算符 | C |= 2 等同于 C = C | 2 |
實(shí)例
請(qǐng)看下面的實(shí)例,了解 C 語(yǔ)言中所有可用的賦值運(yùn)算符:
void assignment_operation(void) {
int a = 21;
int c ;
c = a;
printf("Line 1 - = 運(yùn)算符實(shí)例阿宅,c 的值 = %d\n", c );
c += a;
printf("Line 2 - += 運(yùn)算符實(shí)例,c 的值 = %d\n", c );
c -= a;
printf("Line 3 - -= 運(yùn)算符實(shí)例笼蛛,c 的值 = %d\n", c );
c *= a;
printf("Line 4 - *= 運(yùn)算符實(shí)例洒放,c 的值 = %d\n", c );
c /= a;
printf("Line 5 - /= 運(yùn)算符實(shí)例,c 的值 = %d\n", c );
c = 200;
c %= a;
printf("Line 6 - %= 運(yùn)算符實(shí)例滨砍,c 的值 = %d\n", c );
c <<= 2;
printf("Line 7 - <<= 運(yùn)算符實(shí)例往湿,c 的值 = %d\n", c );
c >>= 2;
printf("Line 8 - >>= 運(yùn)算符實(shí)例,c 的值 = %d\n", c );
c &= 2;
printf("Line 9 - &= 運(yùn)算符實(shí)例惋戏,c 的值 = %d\n", c );
c ^= 2;
printf("Line 10 - ^= 運(yùn)算符實(shí)例领追,c 的值 = %d\n", c );
c |= 2;
printf("Line 11 - |= 運(yùn)算符實(shí)例,c 的值 = %d\n", c );
}
雜項(xiàng)運(yùn)算符 ? sizeof & 三元
下表列出了 C 語(yǔ)言支持的其他一些重要的運(yùn)算符响逢,包括 sizeof 和 ? :绒窑。
運(yùn)算符 | 描述 | 實(shí)例 |
---|---|---|
sizeof() | 返回變量的大小。 | sizeof(a) 將返回 4舔亭,其中 a 是整數(shù)些膨。 |
& | 返回變量的地址蟀俊。 | &a; 將給出變量的實(shí)際地址。 |
* | 指向一個(gè)變量订雾。 | *a; 將指向一個(gè)變量肢预。 |
? : | 條件表達(dá)式 | 如果條件為真 ? 則值為 X : 否則值為 Y |
實(shí)例
請(qǐng)看下面的實(shí)例,了解 C 語(yǔ)言中所有可用的雜項(xiàng)運(yùn)算符:
void miscellaneous_operations(void) {
int a = 4;
short b;
double c;
int *ptr;
/* sizeof 運(yùn)算符實(shí)例 */
printf("Line 1 - 變量 a 的大小 = %lu\n", sizeof(a));
printf("Line 2 - 變量 b 的大小 = %lu\n", sizeof(b));
printf("Line 3 - 變量 c 的大小 = %lu\n", sizeof(c));
/* & 和 * 運(yùn)算符實(shí)例 */
ptr = &a; /* 'ptr' 現(xiàn)在包含 'a' 的地址 */
printf("a 的值是 %d\n", a);
printf("*ptr 是 %d\n", *ptr);
/* 三元運(yùn)算符實(shí)例 */
a = 10;
b = (a == 1) ? 20 : 30;
printf("b 的值是 %d\n", b);
b = (a == 10) ? 20 : 30;
printf("b 的值是 %d\n", b);
}
Line 1 - 變量 a 的大小 = 4
Line 2 - 變量 b 的大小 = 2
Line 3 - 變量 c 的大小 = 8
a 的值是 4
*ptr 是 4
b 的值是 30
b 的值是 20
C 中的運(yùn)算符優(yōu)先級(jí)
運(yùn)算符的優(yōu)先級(jí)確定表達(dá)式中項(xiàng)的組合洼哎。這會(huì)影響到一個(gè)表達(dá)式如何計(jì)算烫映。某些運(yùn)算符比其他運(yùn)算符有更高的優(yōu)先級(jí),例如噩峦,乘除運(yùn)算符具有比加減運(yùn)算符更高的優(yōu)先級(jí)锭沟。
例如 x = 7 + 3 * 2,在這里壕探,x 被賦值為 13冈钦,而不是 20,因?yàn)檫\(yùn)算符 * 具有比 + 更高的優(yōu)先級(jí)李请,所以首先計(jì)算乘法 3*2瞧筛,然后再加上 7。
下表將按運(yùn)算符優(yōu)先級(jí)從高到低列出各個(gè)運(yùn)算符导盅,具有較高優(yōu)先級(jí)的運(yùn)算符出現(xiàn)在表格的上面较幌,具有較低優(yōu)先級(jí)的運(yùn)算符出現(xiàn)在表格的下面。在表達(dá)式中白翻,較高優(yōu)先級(jí)的運(yùn)算符會(huì)優(yōu)先被計(jì)算乍炉。
類別 | 運(yùn)算符 | 結(jié)合性 |
---|---|---|
后綴 | () [] -> . ++ - - | 從左到右 |
一元 | + - ! ~ ++ - - (type)* & sizeof | 從右到左 |
乘除 | * / % | 從左到右 |
加減 | + - | 從左到右 |
移位 | << >> | 從左到右 |
關(guān)系 | < <= > >= | 從左到右 |
相等 | == != | 從左到右 |
位與 AND | & | 從左到右 |
位異或 XOR | ^ | 從左到右 |
位或 OR | | | 從左到右 |
邏輯與 AND | && | 從左到右 |
邏輯或 OR | || | 從左到右 |
條件 | ?: | 從右到左 |
賦值 | = += -= *= /= %=>>= <<= &= ^= |= | 從右到左 |
逗號(hào) | , | 從左到右 |
實(shí)例
請(qǐng)看下面的實(shí)例,了解 C 語(yǔ)言中運(yùn)算符的優(yōu)先級(jí):
void precedence_of_operator(void) {
int a = 20;
int b = 10;
int c = 15;
int d = 5;
int e;
e = (a + b) * c / d; // ( 30 * 15 ) / 5
printf("(a + b) * c / d 的值是 %d\n", e);
e = ((a + b) * c) / d; // (30 * 15 ) / 5
printf("((a + b) * c) / d 的值是 %d\n", e);
e = (a + b) * (c / d); // (30) * (15/5)
printf("(a + b) * (c / d) 的值是 %d\n", e);
e = a + (b * c) / d; // 20 + (150/5)
printf("a + (b * c) / d 的值是 %d\n", e);
}
(a + b) * c / d 的值是 90
((a + b) * c) / d 的值是 90
(a + b) * (c / d) 的值是 90
a + (b * c) / d 的值是 50