一、C語言的關鍵字
C語言的關鍵字是一些編譯器預先定義的具有一定具體含義的字符串。關鍵字共有32個,分爲五大類:
1. 基本數據類型——(9個)
關鍵字 | 含義 |
---|---|
char | 軟件操作的最小數據單元 8bit |
int | 系統單週期最大數據處理單元 32bit/64bit |
short | 特殊長度的限制符(不能大於int) 通常16bit |
long | 特殊長度的限制符(不能小於int) 通常32bit |
float | 浮點型數據,帶小數點 通常32bit |
double | 浮點型數據,帶小數點 通常64bit |
void | 空類型 |
signed | 帶符號類型,用作數值 |
unsigned | 不帶符號,用作內存 |
原碼/補碼/反碼
機器數
一個數在計算機中的二進制表示形式帶符號,正數爲0, 負數爲1,叫做這個數的機器數
例:十進制中的數 +3 ,機器數是00000011。-3 ,機器數是 10000011
真值
帶符號位的機器數對應的真正數值稱爲機器數的真值。
例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1
原碼
原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其餘位表示值。
反碼
正數的反碼是其本身,負數的反碼是在其原碼的基礎上, 符號位不變,其餘各個位取反。
補碼
正數的補碼就是其本身,負數的補碼是在其原碼的基礎上, 符號位不變, 其餘各位取反, 最後+1. (即在反碼的基礎上+1)
爲什麼會有原碼反碼補碼?
計算機無法判斷符號(硬件難於實現),因此使用符號位參與運算。
- 首先來看原碼:
計算十進制的表達式:1-1=0
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
如果用原碼錶示, 讓符號位也參與計算, 顯然對於減法來說, 結果是不正確的。 - 爲了解決原碼做減法的問題, 出現了反碼:
計算十進制的表達式:1-1=0
1 - 1 = 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [0000 0001]反 + [1111 1110]反
= [1111 1111]反 = [1000 0000]原
= -0
會有[0000 0000]原和[1000 0000]原兩個編碼表示0. - 於是補碼的出現, 解決了0的符號以及兩個編碼的問題:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原
= [0000 0001]補 + [1111 1111]補
= [0000 0000]補=[0000 0000]原
這樣0用[0000 0000]表示, 而以前出現問題的-0則不存在了.而且可以用[1000 0000]表示-128。
ASCII碼錶
Bin | Dec | Hex | 縮寫/字符 | 解釋 |
---|---|---|---|---|
0000 0000 | 0 | 00 | NUL(null) | 空字符 |
0000 1000 | 8 | 08 | BS (backspace) | 退格 |
0000 1001 | 9 | 09 | HT (horizontal tab) | 水平製表符 |
0000 1010 | 10 | 0A | LF (NL line feed, new line) | 換行鍵 |
0000 1101 | 13 | 0D | CR (carriage return) | 回車鍵 |
0010 0000 | 32 | 20 | (space) 空格 | |
00110000 | 48-57 | 30-39 | 0-9 數字 | |
01000001 | 65-90 | 41-5A | A-Z 大寫字母 同字母大小寫相差32 | |
01100001 | 97-122 | 61-7A | a-z 小寫字母 | |
01111111 | 127 | 7F | DEL (delete) | 刪除 |
2.自定義數據類型——(4個)
自定義數據類型相當於基本數據類型的集合。
關鍵字 | 含義 | 注意事項 |
---|---|---|
struct | 結構體 | 內存佔用2字節或4字節對齊 |
union | 共用體(聯合體) | 以最大的元素佔用內存 |
enum | 枚舉常量 | 枚舉值是常量,不是變量。不能在程序中用賦值語句再對它賦值。只能把枚舉值賦予枚舉變量,不能把元素的數值直接賦予枚舉變量。枚舉元素不是字符常量也不是字符串常量,使用時不要加單、雙引號 |
typedef | 數據類型別名 |
3.邏輯結構——(11個)
C語言的邏輯結構有三種:順序,分支,循環
關鍵字 | 含義 |
---|---|
if、else | 分支結構 |
switch、case、default | 分支結構 switch條件只能是整形數字 |
do、while | 循環結構 先後順序 條件循環 |
for | 循環結構 次數循環 |
continue | 跳轉 跳出本次循環繼續進行下次循環 |
break | 跳轉 跳出當前循環進入下個語句 |
goto | 不建議使用 |
4.類型修飾符——(6個)
類型修飾符是對資源存放位置的限定
關鍵字 | 含義 |
---|---|
auto | 默認情況 局部變量存放於棧空間 |
register | 限制變量定義在寄存器上的修飾符 存放在寄存器,無法用&取地址 |
static | 靜態 |
const | 定義爲常量,防止被修改 |
extern | 外部引用 外部文件 |
volatile | 編譯優化選項 |
static詳解
- 修飾全局變量:定義全局變量爲靜態全局變量
存放在.data(初始化)和.bss(未初始化)
外部文件無法引用 - 修飾局部變量:定義爲靜態局部變量
存放區域爲.data
生命週期爲整個程序的生命週期,但依舊只有定義他的函數能夠使用
值,初始化爲0,每次調用會讀取上次的值。 - 修飾函數:定義爲靜態函數
只能在本文件調用
const詳解
- 修飾變量
定義變量爲不可改變的。 - 修飾指針
const char *p 修飾的是*p,p指向的內容不能被更改
char * const p 修飾的是p,指針不能被更改
const char * const p 指針和內容都不能被更改 - 修飾函數
□ 修飾輸入參數
值傳遞 無需const保護
指針傳遞 防止更改原有指針指向的內容,對參數內容只讀不寫
5.其它
關鍵字 | 含義 |
---|---|
return | 返回。 |
sizeof | 查看內存容量 |
二、運算符
1. 運算符的分類
類別 | 符號 |
---|---|
算術運算符 | 加 + 減 - 乘 * 除 / 取餘 % |
邏輯運算符 | 與 && 或 || 非 ! |
問號運算 | ? : |
關係運算 | 小於 < 小於等於 <= 大於 > 大於等於 >= 等於 == 不等於 != |
位運算 | 左移 << 右移>> 按位與 & 按位或 | 按位異或 ^ |
賦值運算 | 等於 = 加等於 += 剪等於 -= 等等 |
三目運算 | 表達式A? 表達式B: 表達式C 如果表達式A爲真,那麼表達式B爲整個表達式的值;爲假 , 那麼表達式C爲整個表達式的值。 |
逗號運算 | 從左到右依次計算,最後表達式的值,作爲整個表達式的值。 |
2. 運算優先級
優先級 | 運算符 | 結合方向 |
---|---|---|
1成員包含 | []數組下標 ()圓括號 .成員選擇(對象) ->成員選擇(指針) | 左到右 |
2單目運算 | -負號運算符 (類型)強制類型轉換 ++自增運算符 –自減運算符 | 右到左 |
*取值運算符 &取地址運算符 !邏輯非運算符 ~按位取反運算符 sizeof長度運算符 | ||
3算術運算 | 加減乘除取餘 | 左到右 |
4位移 | << 左移 >> 右移 | 左到右 |
5比較 | > 大於>=大於等於 < 小於 <=小於等於 | 左到右 |
==等於 !=不等於 | ||
6位比較 | &按位與 ^按位異或 按位或 | 左到右 |
7邏輯運算 | &&邏輯與 | |
8條件運算 | ?:條件運算符 | 右到左 |
9賦值運算 | =賦值運算符 /=除後賦值 *=乘後賦值 %=取模後賦值 | 右到左 |
10逗號 | ,逗號運算符 | 左到右 |
3. 神奇的運算
取餘運算:
取一個範圍的數(m% 100)+1 ===> res;得到M進制的一個個位數;循環數據結構的下標
邏輯運算:
返回值0與1 !與~不同
位運算:
<< 左移相當於乘以2 >> 右移相當於除以2
& 與0屏蔽用於清零 與1用於取出 | 或0保留用於取出 或1用於設置
三、C語言的內存使用
1. 指針
指針:內存類型資源地址
指針變量 : 存放指針這個概念的盒子。所有的指針在32位系統中都是4字節。
指針的類型:去掉變量後的內容
指針所指向的類型:去掉*後的內容
指針的值/叫指針所指向的內存區:指向內容的首地址
指針本身所佔據的內存區:在32位系統中都是4字節
指針的加減N:將現有指針指向的內存區加減 指針指向類型的大小 * N
常見的指針類型:
表達式 | 含義 |
---|---|
int p; | 這是一個普通的整型變量 |
int *p; | 首先從 P 處開始,先與*結合,所以說明 P 是一個指針,然後再與 int 結合,說明指針所指向的內容的類型爲 int 型.所以 P 是一個返回整型數據的指針 |
int p[3]; | 首先從 P 處開始,先與[]結合,說明 P 是一個數組,然後與 int 結合,說明數組裏的元素是整型的,所以 P 是一個由整型數據組成的數組 |
int *p[3]; | 首先從 P 處開始,先與[]結合,因爲其優先級比*高,所以 P 是一個數組,然後再與*結合,說明數組裏的元素是指針類型,然後再與 int 結合,說明指針所指向的內容的類型是整型的所以P 是一個由返回整型數據的指針所組成的數組 |
int (*p)[3]; | 首先從 P 處開始,先與*結合,說明 P 是一個指針然後再與[]結合,說明指針所指向的內容是一個數組,然後再與 int 結合,說明數組裏的元素是整型的.所以 P 是一個指向由整型數據組成的數組的指針 |
int **p; | 首先從 P 開始,先與結合,說是 P 是一個指針,然後再與結合,說明指針所指向的元素是指針,然後再與 int 結合,說明該指針所指向的元素是整型數據. |
int p(int); | 從 P 處起,先與()結合,說明 P 是一個函數,然後進入//()裏分析,說明該函數有一個整型變量的參數然後再與外面的 int 結合,說明函數的返回值是一個整型數據 |
Int (*p)(int); | 從 P 處開始,先與指針結合,說明 P 是一個指針,然後與()結合,說明指針指向的是一個函數,然後再與()裏的int 結合,說明函數有一個 int 型的參數,再與最外層的int 結合,說明函數的返回類型是整型,所以 P 是一個指向有一個整型參數且返回類型爲整型的函數的指針 |
int *(*p(int))[3]; | 從 P 開始,先與()結合,說明 P 是一個函數,然後進入()裏面,與 int 結合,說明函數有一個整型變量參數,然後再與外面的*結合,說明函數返回的是一個指針,然後到最外面一層,先與[]結合,說明返回的指針指向的是一個數組,然後再與*結合,說明數組裏的元素是指針,然後再與 int 結合,說明指針指向的內容是整型數據.所以 P 是一個參數爲一個整數且返回一個指向由整型指針變量組成的數組的指針變量的函數. |
int *(*p[3])(void*); | 首先和[]結合,說明p是一個數組 |
然後和*結合,說明數組中的每個元素都是一個指針,
然後和()結合,說明指針指向的是一個函數,
最後,與外層相結合說明這個函數的輸入參數爲void*型,返回值爲int * 型
所以p是一個含有三個元素的數組,每個數組元素都是一個參數爲一個整數且返回一個指向整型指針的函數.
2. 數組
數組是具有一定順序關係的若干個變量的集合,組成數組的各個變量稱爲數組的元素。
數組的元素地址空間是連續的。
<存儲類型> <數據類型 > <數組名>[<表達式>]
數組是內存的一種分配方式,數組名是一個常量符號,一定不要放到=的左邊。
數組的賦值
- 按照標籤逐一處理
int a[10]; [ 0 - 9 ]
a[0] = xx
a[1] = yy;
- 空間定義時,就告知編譯器的初始化情況,空間的第一次賦值,初始化操作
int a[10] = 空間;
- C語言本身,CPU內部本身一般不支持空間和空間的拷貝
int a[10] = {10,20,30}; ====> a[0] = 10; a[1] = 20; a[2] = 30; a[3]=0;
3. 內存分佈
內存的屬性: 1、大小 2、在哪裏
運行時
名稱 | 含義 | 訪問權限 | 備註 |
---|---|---|---|
內核空間 | 應用程序不許訪問(3G-4G) | ||
棧空間 | 局部變量 | RW | 向下增長 |
運行時的堆空間 | malloc | RW | 向上增長 |
全局的數據空間 (未初始化) 0 | static | RW | bss |
全局的數據空間(初始化的) | static | RW | data |
只讀數據段 | “hello world” 字符串常量 | R | TEXT |
代碼段 | code | R | TEXT |
存儲時:
名稱 | 標識 | 訪問權限 | 備註 |
---|---|---|---|
數據區(未初始化) | bss | RW | |
數據區(初始化的) | data | RW | |
代碼段 | code | R | TEXT |
棧空間:運行時,函數內部使用的變量,函數一旦返回,就釋放,生存週期是函數內
堆空間:運行時,可以自由,自我管理的分配和釋放的空間,生存週期是由程序員來決定
四、函數
1. 函數概述
一堆代碼的集合,用一個標籤去描述它,爲了實現代碼的複用化
標籤 —– 函數名,函數具備3要素:
1、函數名 (地址)
2、輸入參數
3、返回值
在定義函數時,必須將3要素告知編譯器。
2. 輸入參數
承上啓下的功能
- 調用者:
函數名(要傳遞的數據) //實參 - 被調者:
函數的具體實現
函數的返回值 函數名(接收的數據) //形參
值傳遞
上層調用者 保護自己空間值不被修改的能力
地址傳遞
上層,調用者 讓下層 子函數 修改自己空間值的方式
- 子函數看看空間裏的情況 const *
- 子函數反向修改上層空間裏的內容 char *
3. 返回值
提供啓下功能的一種表現形式