C語(yǔ)言學(xué)習(xí)二 — 變量常量存儲(chǔ)類運(yùn)算符

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á)式:

  1. 左值(lvalue):指向內(nèi)存位置的表達(dá)式被稱為左值(lvalue)表達(dá)式婚脱。左值可以出現(xiàn)在賦值號(hào)的左邊或右邊今魔。
  2. 右值(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)單的定義常量的方式:

  1. 使用 #define 預(yù)處理器凯旭。
  2. 使用 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

代碼已上傳github滤馍,點(diǎn)擊此處即可到達(dá)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末岛琼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子巢株,更是在濱河造成了極大的恐慌槐瑞,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阁苞,死亡現(xiàn)場(chǎng)離奇詭異困檩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)那槽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門悼沿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人骚灸,你說(shuō)我怎么就攤上這事糟趾。” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵拉讯,是天一觀的道長(zhǎng)涤浇。 經(jīng)常有香客問(wèn)我,道長(zhǎng)魔慷,這世上最難降的妖魔是什么只锭? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮院尔,結(jié)果婚禮上蜻展,老公的妹妹穿的比我還像新娘。我一直安慰自己邀摆,他們只是感情好纵顾,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著栋盹,像睡著了一般施逾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上例获,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天汉额,我揣著相機(jī)與錄音,去河邊找鬼榨汤。 笑死蠕搜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的收壕。 我是一名探鬼主播妓灌,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蜜宪!你這毒婦竟也來(lái)了虫埂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤圃验,失蹤者是張志新(化名)和其女友劉穎告丢,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體损谦,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年岳颇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了照捡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡话侧,死狀恐怖栗精,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤悲立,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布鹿寨,位于F島的核電站,受9級(jí)特大地震影響薪夕,放射性物質(zhì)發(fā)生泄漏脚草。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一原献、第九天 我趴在偏房一處隱蔽的房頂上張望馏慨。 院中可真熱鬧,春花似錦姑隅、人聲如沸写隶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)慕趴。三九已至,卻和暖如春鄙陡,著一層夾襖步出監(jiān)牢的瞬間冕房,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工柔吼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毒费,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓愈魏,卻偏偏與公主長(zhǎng)得像觅玻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子培漏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容