逆向基础之C语言 第一篇
逆向之C語言
- 00_C語言概述
- 知識(shí)點(diǎn)1 【寫代碼的過程】
- Visual C++ 6.0
- 安裝VC6.0
- 配置兼容性
- 創(chuàng)建c工程
- 添加源文件
- 知識(shí)點(diǎn)2 【完整的C代碼分析】
- 1、案例1:hello iot
- 2、案例2:求圓的面積
- 3、案例3:用分函數(shù)的方式求兩個(gè)數(shù)的和
- 01_C語言的基本語法
- 知識(shí)點(diǎn)1【數(shù)據(jù)類型】
- 案例:驗(yàn)證數(shù)據(jù)類型的長(zhǎng)度
- 知識(shí)點(diǎn)2【unsigned和signed】(重要)
- 1、無符號(hào)數(shù)unsigned
- 2、有符號(hào)數(shù)signed 默認(rèn)一般省略
- 知識(shí)點(diǎn)3 【結(jié)構(gòu)體struct 和 共用體union】
- 1、struct 結(jié)構(gòu)體中的 成員擁有 獨(dú)立的空間
- 2、union 共用體中的成員 共享同一份空間
- 知識(shí)點(diǎn)4【enum枚舉 和 void無類型】
- 知識(shí)點(diǎn)5【其他關(guān)鍵字】(了解)
- 1、register 寄存器變量
- 2、typedef 為已有的類型取一個(gè)別名
- 3、volatile 防止編譯器優(yōu)化 強(qiáng)制訪問內(nèi)存操作
- 知識(shí)點(diǎn)6 【常量與變量】(重要)
- 1、常量 值不能被修改 (千萬不能反過來說:值不能被修改的就是常量X)
- 2、變量 系統(tǒng)根據(jù)變量的類型 開辟對(duì)應(yīng)的空間 其值可以被修改
- 知識(shí)點(diǎn)7【八進(jìn)制 十進(jìn)制 十六進(jìn)制】
- 知識(shí)點(diǎn)9 【整型變量的操作 - 讀(取值)、寫(賦值)】
- 1、取值與賦值——讀寫操作
- 2、整型的輸出形式
- 知識(shí)點(diǎn)10 【實(shí)型 常量】
- 知識(shí)點(diǎn)11 【字符常量和變量】(重要)
- 1、字符常量char
- 案例: 鍵盤輸入“abc”,只取‘a(chǎn)’和‘c’
- 知識(shí)點(diǎn)12 【轉(zhuǎn)義字符】
- 知識(shí)點(diǎn)13 【字符串】“”雙引號(hào)作用
- 知識(shí)點(diǎn)14 【輸出的格式回顧】(了解)
- 知識(shí)點(diǎn)15 【typedef】
- 02_C語言的基本語句
- 知識(shí)點(diǎn)1【數(shù)據(jù)類型轉(zhuǎn)換】
- 1、自動(dòng)類型轉(zhuǎn)換(保證精度不丟失)
- **轉(zhuǎn)化的方向**
- 案例:有符號(hào)和無符號(hào)的轉(zhuǎn)換
- 案例:int和double的轉(zhuǎn)換
- 案例:char和short的類型轉(zhuǎn)換
- 2、強(qiáng)制類型轉(zhuǎn)換
- 知識(shí)點(diǎn)2 【運(yùn)算符】
- 1、算術(shù)運(yùn)算符(+、-、*、/、%)
- 案例:鍵盤輸入一個(gè)數(shù) ,是否能被3整除
- 2、邏輯運(yùn)算符(!、&&、||)
- ① 邏輯非 ——!0 == 真 、 !真 == 假
- ② 邏輯與 &&(重要)
- ③邏輯或 ||
- 綜合案例:
- 知識(shí)點(diǎn)3 【位運(yùn)算符】二進(jìn)制位操作(<< 、>> 、& 、| 、~ 、^)
- &:按位與
- |:按位或
- 案例:將1010 1010的第2、3位變成1,其他不變
- ~:按位取反
- ^:按位異或 (重要)
- 案例:將1010 1010的第0位發(fā)生翻轉(zhuǎn)(要將哪位翻轉(zhuǎn),就將它與1異或)
- <<:左移運(yùn)算符(左邊丟棄,右邊補(bǔ)0)
- >>:右移運(yùn)算符
- 知識(shí)點(diǎn)4【三目運(yùn)算符】?:
- 案例
- 知識(shí)點(diǎn)5【逗號(hào)運(yùn)算符】
- 案例:逗號(hào)運(yùn)算符
- 知識(shí)點(diǎn)6【符合運(yùn)算符】
- 案例
- 知識(shí)點(diǎn)7【自增自減 運(yùn)算符】
- 知識(shí)點(diǎn)7【優(yōu)先級(jí)】分析已有的代碼
- 知識(shí)點(diǎn)8【if 語句】
- 1、如果只在乎項(xiàng)目的一個(gè)結(jié)果,選擇if
- 2、如果項(xiàng)目只有**兩種結(jié)果**,且**不會(huì)同時(shí)出現(xiàn)**。請(qǐng)選擇if....else....
- 3、如果一個(gè)項(xiàng)目 有多個(gè)結(jié)果 且不同時(shí)出現(xiàn)。選擇if....else if...else if...else
- 4、一個(gè)項(xiàng)目有多個(gè)結(jié)果,不確定是否同時(shí)出現(xiàn)
- 知識(shí)點(diǎn)9【switch 選擇語句】
- 案例:有時(shí)候break可以省略
- 03_循環(huán)語句及數(shù)組
- 知識(shí)點(diǎn)1 【for循環(huán)】
- 案例: 求1~100的和
- 案例:
- 案例:break只能跳出離它最近的一層循環(huán)
- continue
- 案例:求出0~100的所有偶數(shù)的和
- break和continue的區(qū)別
- 循環(huán)嵌套循環(huán)
- 知識(shí)點(diǎn)2【while 循環(huán) 和 do...while 循環(huán)】
- 案例:
- 案例
- 知識(shí)點(diǎn)3【goto 跳轉(zhuǎn)】(慎用!)
- 知識(shí)點(diǎn)4【數(shù)組的概述】
- 知識(shí)點(diǎn)5【一維數(shù)值數(shù)組】
- 1、數(shù)組的定義
- 案例1:遍歷數(shù)組
- 案例2:數(shù)組的初始化
- 全部初始化:
- 部分初始化:
- 拓展:特殊初始化
- 2、數(shù)組的空間大小(重要)
- 遍歷數(shù)組
- 案例:
- 3、數(shù)組元素的操作
- 案例:定義一個(gè)數(shù)組 5個(gè)元素,每個(gè)元素int類型,獲取鍵盤輸入
- 作業(yè):定義一個(gè)數(shù)組 5個(gè)元素,每個(gè)元素int類型,獲取鍵盤輸入,請(qǐng)求出數(shù)組的最大值,最小值,平均值。
- 知識(shí)點(diǎn)6【二維數(shù)組】
- 1、二維數(shù)組的定義
- 二維數(shù)組的遍歷:
- 案例:
- 2、二維數(shù)組的初始化
- 分段初始化:用大括號(hào)里面的大括號(hào),明確的表示一行
- 連續(xù)初始化:放滿一行才能放下一行
- 案例:
- 04_數(shù)組與函數(shù)
- 知識(shí)點(diǎn)1 【作業(yè)講解】
- **作業(yè):定義int arr[3][4]的二維數(shù)組,獲取鍵盤輸入,并求出每一行的平均值。**
- 案例:求每一列的平均值
- 知識(shí)點(diǎn)2 【字符數(shù)組】(重要)
- 字符數(shù)組的初始化
- 字符數(shù)組的遍歷
- 逐個(gè)字符初始化和字符串初始化的區(qū)別
- 字符數(shù)組獲取鍵盤的字符串
- scanf和%s使用的時(shí)候有個(gè)缺點(diǎn),遇到**空格**會(huì)結(jié)束輸入
- **gets()缺點(diǎn):獲取鍵盤輸入的時(shí)候,不會(huì)管buf的大小,容易造成內(nèi)存污染**
- fgets():既可以獲取帶空格的字符串,也可以保證buf的不越界
- 案例:
- 提高案例:字符串的大小寫的轉(zhuǎn)換
- 知識(shí)點(diǎn)3【二維字符數(shù)組】(了解)
- 二維字符數(shù)組獲取鍵盤輸入的字符串:
- 知識(shí)點(diǎn)4 【函數(shù)概述】
- 1、函數(shù)的定義
- 2、函數(shù)的聲明
- 3、函數(shù)的調(diào)用
- 知識(shí)點(diǎn)5 【函數(shù)的參數(shù)】
- 1、如果函數(shù)的形參什么都不寫 在調(diào)用的時(shí)候可以傳實(shí)參,只是實(shí)參得不到使用
- 2、如果函數(shù)沒有參數(shù),請(qǐng)將形參寫成void
- 3、函數(shù)參數(shù)的傳遞
00_C語言概述
知識(shí)點(diǎn)1 【寫代碼的過程】
編輯器:程序員寫代碼的過程(記事本、VC6.0、vim…)(讓程序員看懂)
編譯器:查看代碼的語法錯(cuò)誤,生成匯編語言。
匯編器:將生成好的匯編語言生成二進(jìn)制語言(也叫做目標(biāo)文件)
連接器:將生成好的二進(jìn)制語言+用到的庫(kù)+啟動(dòng)代碼=====>可執(zhí)行文件
- Windows開發(fā)特點(diǎn):
- 在電腦上裝一個(gè)VC或者其他集成開發(fā)環(huán)境
- 編輯程序——》編譯程序——》看現(xiàn)象——》有問題——》修改程序——》調(diào)試程序 ——》看現(xiàn)象
- Linux開發(fā)特點(diǎn):
- Linux下程序開發(fā)大多數(shù)通過在本地安裝虛擬機(jī)、物理機(jī)或者網(wǎng)絡(luò)連接到服務(wù)器完成
- 出于效率、遠(yuǎn)程開發(fā)、嵌入式開發(fā)的考慮:開發(fā)方式太多 是在命令行下完成,沒有很好的集成開發(fā)環(huán)境供我們使用
Visual C++ 6.0
安裝VC6.0
Visual C++6.0下載地址:https://pan.baidu.com/s/1UoyJD6FUARS2EvDdC9l7qA 提取碼: 1314.
解壓?jiǎn)螕舭惭b即可,默認(rèn)下一步
配置兼容性
- 鼠標(biāo)右鍵點(diǎn)擊桌面生成的快捷方式,選擇屬性
- 點(diǎn)擊兼容性,找到兼容模式的位置,在“以兼容模式運(yùn)行這個(gè)程序”前打勾,在下方下拉菜單中選擇Windows XP(Service Pack3),點(diǎn)擊確定即可
-
創(chuàng)建c工程
打開VC6.0,關(guān)閉每日提示
文件——》新建——》工程——》win32 console Application控制臺(tái)程序——》確定
從0開始學(xué),選擇一個(gè)空工程——》完成
單擊FileView就可以看到工程的目錄結(jié)構(gòu)
添加源文件
文件——》新建——》文件——》C++ Source File——》寫文件名(后綴名為.C,若不寫則默認(rèn)為.cpp為C++源文件)——》確定
知識(shí)點(diǎn)2 【完整的C代碼分析】
1、案例1:hello iot
# include<stdio.h> //std是標(biāo)準(zhǔn)的意思 i表示輸入 o表示輸出(標(biāo)準(zhǔn)的輸入輸出頭文件) // 雙斜杠//是行注釋 /**/是塊注釋,注意塊注釋不能嵌套//()里面的是函數(shù)的形參(函數(shù)外部將數(shù)據(jù)傳遞到函數(shù)內(nèi)部的橋梁) int main(int argc, char *argv[]) //main主函數(shù) 是程序的入口,有且僅有一個(gè)主函數(shù) //main左邊的int代表的是函數(shù)的返回類型 {// 使用任何東西 必先存在printf("hello iot\n");// printf來自系統(tǒng)庫(kù)文件,printf:將雙引號(hào)的字符串輸出(o)到終端上return 0;//0是一個(gè)int類型 } //{}函數(shù)的功能都在大括號(hào)里面實(shí)現(xiàn),每敲一行代碼記得用tab縮進(jìn),不要用空格 //分號(hào)是C語言的結(jié)束標(biāo)記 //如果你的代碼一閃而過 可以用帶阻塞的代碼 getchar(); // int char return都是關(guān)鍵字總結(jié):
1、main有且只有一個(gè)
2、printf的頭文件是stdio.h
3、注釋 行注釋和塊注釋(塊注釋不能嵌套)
調(diào)整VC6.0字體大小:工具——》選項(xiàng)——》三角符號(hào)往后點(diǎn)有個(gè)格式——》選擇原窗口——》選擇合適大小
2、案例2:求圓的面積
知道的條件:半徑r
算法:面積=πrr
解析步驟:
①r通過鍵盤輸入或者用特定的值
②定義一個(gè)面積變量 area=πrr
③將圓的面積輸出到終端上
運(yùn)行結(jié)果:
3、案例3:用分函數(shù)的方式求兩個(gè)數(shù)的和
步驟分析:
1、定義兩個(gè)變量data1、data2 獲取鍵盤輸入
2、定義一個(gè)函數(shù) 去計(jì)算上面兩個(gè)變量data1、data2的和
在函數(shù)內(nèi)部計(jì)算計(jì)算(怎么將數(shù)據(jù)傳遞到函數(shù)內(nèi)部?)
需要用形參 將data1 data2傳遞到函數(shù)內(nèi)部
3、得到函數(shù)的計(jì)算結(jié)果(怎么得到呢?)
通過函數(shù)的返回值 得到函數(shù)的計(jì)算結(jié)果
運(yùn)行結(jié)果:
01_C語言的基本語法
知識(shí)點(diǎn)1【數(shù)據(jù)類型】
數(shù)據(jù)分為不同類型 是為了 更加合理的利用內(nèi)存空間
計(jì)算機(jī)存儲(chǔ)的是二進(jìn)制,一位二進(jìn)制只能存放0或者1(低電平或高電平)
1byte=8bit (0000 0000~ 1111 1111)
1kb=1024byte 10月24日是程序員節(jié)
1MB=1024kb
1GB=1024MB
1TB=1024GB
1PB=1024TB
1EB=1024PB
-----------------------------------在32位平臺(tái)-----------------------------------------
char 字符類型 占1個(gè)字節(jié) (8個(gè)二進(jìn)制位)
short 短整型 占2個(gè)字節(jié) (16個(gè)二進(jìn)制位)
int 整型 占4個(gè)字節(jié)(32個(gè)二進(jìn)制位)
long 長(zhǎng)整型 占4字節(jié)空間(32個(gè)二進(jìn)制位)
float 單精度浮點(diǎn)型 占4字節(jié)空間(32個(gè)二進(jìn)制位)
double 雙精度浮點(diǎn)型 占8字節(jié)空間(64個(gè)二進(jìn)制位)
-----------------------------------在64位平臺(tái)-----------------------------------------
char 字符類型 占1個(gè)字節(jié) (8個(gè)二進(jìn)制位)
short 短整型 占2個(gè)字節(jié) (16個(gè)二進(jìn)制位)
int 整型 占4個(gè)字節(jié)(32個(gè)二進(jìn)制位)
long 長(zhǎng)整型 占8字節(jié)空間(64個(gè)二進(jìn)制位)
float 單精度浮點(diǎn)型 占4字節(jié)空間(32個(gè)二進(jìn)制位)
double 雙精度浮點(diǎn)型 占8字節(jié)空間(64個(gè)二進(jìn)制位)
案例:驗(yàn)證數(shù)據(jù)類型的長(zhǎng)度
sizeof是測(cè)量類型的長(zhǎng)度
#include<stdio.h> int main(int argc,char *argv[]) {printf("sizeof(char)=%d\n",sizeof(char));printf("sizeof(short)=%d\n",sizeof(short));printf("sizeof(int)=%d\n",sizeof(int));printf("sizeof(long)=%d\n",sizeof(long));printf("sizeof(float)=%d\n",sizeof(float));printf("sizeof(double)=%d\n",sizeof(double));return 0; }運(yùn)行結(jié)果:
知識(shí)點(diǎn)2【unsigned和signed】(重要)
1、無符號(hào)數(shù)unsigned
數(shù)據(jù)沒有符號(hào)位,自身所有二進(jìn)制位都是數(shù)據(jù)位
比如:unsigned char ——》 0000 0000~ 1111 1111
2、有符號(hào)數(shù)signed 默認(rèn)一般省略
二進(jìn)制的最高位為符號(hào)位,其他為是數(shù)據(jù)位
signed char ——》 xxxx xxxx(x為0或1)
最高位為1表示負(fù)數(shù),最高位為0表示正數(shù)
比如:一個(gè)字節(jié): -10==1000 1010
案例:
#include<stdio.h> int main(int argc,char *argv) {//定義一個(gè)有符號(hào)intsigned int num1=10; //系統(tǒng)給num1開辟4字節(jié)的空間(這個(gè)4字節(jié)的最高位是符號(hào)位)// signed 默認(rèn)是省略的(推薦)int num2=10; //num2也是有符號(hào)數(shù)//unsigned表示無符號(hào)數(shù) 不能省略unsigned int num3=10;return 0; }知識(shí)點(diǎn)3 【結(jié)構(gòu)體struct 和 共用體union】
1、struct 結(jié)構(gòu)體中的 成員擁有 獨(dú)立的空間
struct data1{char a;short b;int c; }; a b c就是結(jié)構(gòu)體data1中的成員2、union 共用體中的成員 共享同一份空間
union data2{ char a; short b; int c; };
知識(shí)點(diǎn)4【enum枚舉 和 void無類型】
1、enum枚舉 將變量要賦值的值一一列舉出來
enum BOOL(false,true);
enum BOOL bool=false;
2、void 無類型 (重要)
不能用void定義變量
int num; // √
void num; //X 系統(tǒng)不能確定給num開辟多大的空間
知識(shí)點(diǎn)5【其他關(guān)鍵字】(了解)
auto 自動(dòng)類型 ,register 寄存器變量,static 靜態(tài)變量,const 只讀變量
sizeof 測(cè)類型的大小
typedef 為已有的類型 重新取一個(gè)別名
volatile 防止編譯器優(yōu)化
1、register 寄存器變量
總結(jié):
1、如果沒有顯示表明register,就類似int num,如果num被高頻繁使用系統(tǒng)也會(huì)放入寄存器中。
2、register int num; //顯示的將num放入寄存器中
3、寄存器的變量不能取地址 &num(X)
2、typedef 為已有的類型取一個(gè)別名
#include<stdio.h> void test01() { register int num=10;// %p輸出地址//printf("%p\n",&num); //**錯(cuò)誤**,不能對(duì)寄存器變量 取地址 }typedef int INT32; //給已有的int類型 取了一個(gè)別名叫INT32 void test02() {int num1=10;INT32 num=20;printf("num1=%d\n",num1);printf("num2=%d\n",num2); }int main(int argc,char *argv[]){test02();//想運(yùn)行那個(gè)就寫哪個(gè)return 0; }3、volatile 防止編譯器優(yōu)化 強(qiáng)制訪問內(nèi)存操作
知識(shí)點(diǎn)6 【常量與變量】(重要)
1、常量 值不能被修改 (千萬不能反過來說:值不能被修改的就是常量X)
10 20 4.14 ‘a(chǎn)’ “abv”
2、變量 系統(tǒng)根據(jù)變量的類型 開辟對(duì)應(yīng)的空間 其值可以被修改
變量名num代表的是空間的內(nèi)容
操作變量名就是對(duì)空間 內(nèi)容 的操作
變量名的命名規(guī)則:由數(shù)字字母下劃線組成,但是不能以數(shù)字開頭
建議:小寫英文字母 + "_"線 構(gòu)成(C語言命名風(fēng)格)
C++一般用小駝峰法命名:numName
知識(shí)點(diǎn)7【八進(jìn)制 十進(jìn)制 十六進(jìn)制】
十進(jìn)制: 0~9
八進(jìn)制:0~7
十六進(jìn)制:0 ~ 9 ,a ~ f
八進(jìn)制 十進(jìn)制 十六進(jìn)制都是整型的輸出形式
十進(jìn)制輸出 %d %u %ld %lu
八進(jìn)制輸出 %o
十六進(jìn)制輸出 %x
八進(jìn)制是以0開頭
printf("八進(jìn)制:num=%#o\n",num); //0144十六進(jìn)制是以0x開頭
printf("十六進(jìn)制:num=%#x\n",num); //0x64不同的進(jìn)制僅僅是數(shù)據(jù)的表現(xiàn)形式, 并不能修改數(shù)據(jù)本身
知識(shí)點(diǎn)9 【整型變量的操作 - 讀(取值)、寫(賦值)】
1、取值與賦值——讀寫操作
void test01() {//在大括號(hào)內(nèi)部定義的變量叫局部變量(局部變量不初始化,內(nèi)容隨機(jī))int data=0;int num=0;printf("num=%d\n",num);// 讀操作 取值//寫操作 賦值 num=100;printf("num=%d\n",num);data=num; //將右邊的值賦值給左邊 ,對(duì)于num來說是讀取它的值100(讀操作),賦值給data(寫操作)printf("data=%d\n",data);//獲取鍵盤輸入printf("請(qǐng)輸入一個(gè)int數(shù)據(jù):");scanf("%d",&data); //&data 代表的是data空間的起始地址printf("data=%d\n",data); }運(yùn)行結(jié)果:
2、整型的輸出形式
void test02() {int num1=0;//%d 有符號(hào)int數(shù)據(jù)輸出printf("num1=%d\n",num1);unsigned int num2=0;//%u 無符號(hào)int數(shù)據(jù)輸出 (u是unsigned的簡(jiǎn)寫)printf("num2=%u\n",num2)long num3=0;//%ld 有符號(hào)long型數(shù)據(jù)輸出printf("num3=%ld\n",num3);unsigned long num4=0;//%lu 無符號(hào)long型數(shù)據(jù)輸出printf("num3=%lu\n",num4);long long num5=0;//%ld 有符號(hào)long long型數(shù)據(jù)輸出printf("num3=%lld\n",num3);unsigned long long num6=0;//%lu 無符號(hào)long long型數(shù)據(jù)輸出printf("num3=%llu\n",num4);//注意:VC6.0不支持long long但在其他集成環(huán)境支持short num7=0; //short本來就是整型,所以一般不寫int// %hd是有符號(hào)short數(shù)據(jù)輸出printf("num7=%hd\n",num7);short num8=0; //short本來就是整型,所以一般不寫int// %hu是無符號(hào)short數(shù)據(jù)輸出printf("num8=%hu\n",num8); }unsigned short num6=0;
scanf(“num6=%hu\n”,num6); //輸入
x
知識(shí)點(diǎn)10 【實(shí)型 常量】
注意:賦值語句 等號(hào) 兩邊類型盡量保證一致
%lf double型浮點(diǎn)型
加f的是float類型,不加f的是double類型
void test03() {//不以f結(jié)尾的實(shí)型常量 為double類型printf("sizeof(3.14)=%d\n",sizeof(3.14));//8byte//sizeof針對(duì)于變量可以不加小括號(hào),針對(duì)類型要加小括號(hào)//為了通用 最好都加小括號(hào)//以f結(jié)尾的實(shí)型常量 為float類型printf("sizeof(3.14)=%d\n",sizeof(3.14f));//4bytefloat f=3.14; //有沒有問題? 賦值語句要保證兩邊類型相同// f是float類型4字節(jié) 3.14是double類型 8字節(jié)//把8字節(jié)賦值給4字節(jié)(這樣賦值是有問題的) float f=3.14f;(√)//%f輸出 float數(shù)據(jù)printf("f=%f\n",f);//%lf 輸出 double數(shù)據(jù)double d=3.14;printf("%d=%lf\n",d)scanf("%f",&f);scanf("%lf",&d);}float類型占四個(gè)字節(jié)
double類型占八個(gè)字節(jié)
知識(shí)點(diǎn)11 【字符常量和變量】(重要)
直接常量:用單引號(hào)括起來,如:‘a(chǎn)’ 、 ‘b’ 、‘12’等
轉(zhuǎn)義字符:以反斜杠\開頭,后面跟一個(gè)或者幾個(gè)字符,如’\n’ '\t’等,分別代表?yè)Q行、橫向跳格
1、字符常量char
void test01() {// %c輸出的是字符 printf("%c\n",'a');//字符常量//字符變量//ch存儲(chǔ)的是'a'的ASCII值char ch='a';// %c 輸出的是符號(hào)本身printf("ch=%c\n",ch);// ch=a// %d 輸出的是字符的ASCII值printf("ch=%d\n",ch);// ch=97// 'a' 單引號(hào)表示取字符的ASCII// 'a'==97是完全等價(jià)ch=97;printf("ch=%c\n",ch); //ch=aprintf("ch=%d\n",ch); //ch=97ch=ch+1;printf("ch=%c\n",ch); //ch=bprintf("ch=%d\n",ch); //ch=98}ASCII碼表:
總結(jié):
1、‘a(chǎn)’ 單引號(hào)表示取a的ASCII值
2、字符在計(jì)算機(jī)中存儲(chǔ)的是ASCII
3、‘a(chǎn)’==97
思考:
char ch='a'; printf("%d\n",sizeof('a'));//4byte sizeof測(cè)量的是小括號(hào)里面類型的長(zhǎng)度 printf("%d\n",sizeof(char));//1byte 為什么?‘a(chǎn)’,單引號(hào)是取字符的ASCII值——》97,本質(zhì)是sizeof(97); 97是int類型,所以是4byte。
字符類型如何去獲取鍵盤輸入呢?
void test03() {char ch;printf("請(qǐng)輸入一個(gè)字符");//字符變量獲取鍵盤輸入scanf("%c",&ch);//scanf中%c只能**提取一個(gè)字符**printf("ch=%c\n",ch);//輸出字符用%cprintf("ch=%d\n",ch);//輸出ASCII用%d//ch=getchar();//這也是獲取一個(gè)字符,把值賦給變量ch//getchar是一個(gè)函數(shù)調(diào)用,其實(shí)scanf也是一個(gè)函數(shù)調(diào)用 }運(yùn)行結(jié)果:
案例: 鍵盤輸入“abc”,只取‘a(chǎn)’和‘c’
char ch1,ch2;printf("請(qǐng)輸入abc:");//提取ach1=getchar();getchar();//丟棄一個(gè)字符ch2=getchar();//提取cprintf("ch1=%c\n",ch1);printf("ch2=%c\n",ch2);運(yùn)行結(jié)果:
知識(shí)點(diǎn)12 【轉(zhuǎn)義字符】
// '\n'換行 '\t' tab//printf("##%c##\n",'\\');//兩個(gè)反斜杠輸出一個(gè)反斜杠//printf("#%%90#\n");//兩個(gè)百分號(hào)輸出一個(gè)百分號(hào)//ABCD中哪兩個(gè)相等?BC//判斷哪兩個(gè)相等,其實(shí)就是查看這兩個(gè)在計(jì)算機(jī)中存放的ASCII值是不是一樣printf("A:%d\n",'0');//字符0的ASCII是48 字符本質(zhì)存放的就是ASCIIprintf("B:%d\n",'\0');//’\0‘的ASCII值是0printf("C:%d\n",0); //0printf("D:%d\n","0");//字符串0 取的是字符0的地址
知識(shí)點(diǎn)13 【字符串】“”雙引號(hào)作用
%s的本質(zhì)作用就是:從字符串的首元素地址開始,逐個(gè)字符輸出,遇到’\0’自動(dòng)結(jié)束輸出(重要)
請(qǐng)描述‘a(chǎn)’和“a”的區(qū)別:
1、單引號(hào)a只占一個(gè)字節(jié),雙引號(hào)a占2個(gè)字節(jié)(一個(gè)字節(jié)存放字符a,一個(gè)字節(jié)存放\0)
2、'a’取的是字符a的ASCII值,雙引號(hào)a取的是字符串a(chǎn)的首元素的地址
"ab"作為類型代表的的字符串占空間的大小
“ab”作為地址 代表的是字符串 首元素 的地址
知識(shí)點(diǎn)14 【輸出的格式回顧】(了解)
格式化輸出字符:
%d 十進(jìn)制有符號(hào)整數(shù)
%x 以十六進(jìn)制表示的整數(shù)
%f float型浮點(diǎn)數(shù)
%e 指數(shù)形式的浮點(diǎn)數(shù)
%c 單個(gè)字符
%u 十進(jìn)制無符號(hào)整數(shù)
%o 一八進(jìn)制表示的整數(shù)
%lf double型浮點(diǎn)數(shù)
%s 字符串
%p 指針的值
特殊應(yīng)用:
%3d , %03d , %-3d , %5.2f
運(yùn)行結(jié)果:
知識(shí)點(diǎn)15 【typedef】
為已有的類型重新取個(gè)別名
★步驟:
1、用已有的類型定義一個(gè)變量
2、用別名替換變量名
3、在整個(gè)表達(dá)式的前方加上typedef
02_C語言的基本語句
知識(shí)點(diǎn)1【數(shù)據(jù)類型轉(zhuǎn)換】
1、自動(dòng)類型轉(zhuǎn)換(保證精度不丟失)
轉(zhuǎn)化的方向
案例:有符號(hào)和無符號(hào)的轉(zhuǎn)換
int data1=-20; unsigned int data2=10;//有符號(hào)數(shù)data1和無符號(hào)數(shù)data2進(jìn)行轉(zhuǎn)換的時(shí)候//會(huì)先將data1轉(zhuǎn)換為無符號(hào)(-20的補(bǔ)碼——》很大的正數(shù))//很大的數(shù) + 10 必然 >0if(data1+data2>0){printf(">0\n");// √}else if(data1+data2<0){printf("<0\n");}運(yùn)行結(jié)果是:大于0
案例:int和double的轉(zhuǎn)換
int data1=10;//int和double轉(zhuǎn)換時(shí),會(huì)將int轉(zhuǎn)換為doubleprintf("%d\n",sizeof(data1+3.14));// double是8字節(jié)案例:char和short的類型轉(zhuǎn)換
char ch='a';short data=20;//由于char,short自身字節(jié)數(shù)過小,很容易溢出//所以,只要char,short參與運(yùn)算,都會(huì)將自身轉(zhuǎn)換成intprintf("%d\n",sizeof(ch+ch));//4printf("%d\n",sizeof(data+ch));//4printf("%d\n",sizeof(data+data));//42、強(qiáng)制類型轉(zhuǎn)換
(類型說明符)(表達(dá)式)
例如:
(float)a;
(int)(x+y);
注意:無論是強(qiáng)制轉(zhuǎn)換還是自動(dòng)轉(zhuǎn)換,都只是為了本次運(yùn)算的需要,而對(duì)變量的數(shù)據(jù)長(zhǎng)度進(jìn)行臨時(shí)性轉(zhuǎn)換,而不改變數(shù)據(jù)定義的類型。
知識(shí)點(diǎn)2 【運(yùn)算符】
運(yùn)算對(duì)象:常量、變量、函數(shù)(返回值)等
1、算術(shù)運(yùn)算符(+、-、*、/、%)
a/b (a,b都為整數(shù)) 取整
%取余
案例:鍵盤輸入一個(gè)數(shù) ,是否能被3整除
int num=0;//鍵盤輸入一個(gè)整數(shù)printf("請(qǐng)輸入一個(gè)整型數(shù)據(jù):");scanf("%d\n",&num);//判斷能否被3整除if(num%3==0){printf("ok\n");}else{printf("no\n");} printf("%d\n",5/2);//如果反斜杠兩邊都是整數(shù),就是單純的取整 2printf("%f\n",5/2.0f);//如果有浮點(diǎn)型,就是真正的除法 2.5運(yùn)行結(jié)果:
2、邏輯運(yùn)算符(!、&&、||)
① 邏輯非 ——!0 == 真 、 !真 == 假
printf("%d\n",!1);//0printf("%d\n",!0);//1//C中0為假,其他都為真 -1也是真printf("%d\n",!-1);//0② 邏輯與 &&(重要)
A&&B —— A、 B同時(shí)為真 則 整個(gè)表達(dá)式,AB只要有一個(gè)為假,結(jié)果就為假。
if((3>2) && (5>4)){printf("ok\n");//ok}else{printf("no\n");}邏輯與有短路特性
A&&B ——》如果發(fā)現(xiàn)A為假,系統(tǒng)不會(huì)判斷執(zhí)行B,這就是短路特性
③邏輯或 ||
A||B 只要AB任意一個(gè)為真,整個(gè)表達(dá)式都為真,AB同時(shí)為假的時(shí)候,結(jié)果才為假。
邏輯非也有短路特性:只要A為真,編譯器不會(huì)判斷B的真假
int num=10;printf("比較之前num=%d\n",num);//10(3>2) || (num=100);printf("比較之后num=%d\n",num);//10 num=100得不到執(zhí)行綜合案例:
知識(shí)點(diǎn)3 【位運(yùn)算符】二進(jìn)制位操作(<< 、>> 、& 、| 、~ 、^)
&:按位與
語法:全1為1,其他為0
1010 1010 & 1111 0000 -------------------1010 0000特點(diǎn):和1相與 保持不變,和0相與 清零
應(yīng)用場(chǎng)景:將固定位清零
|:按位或
語法:有1就為1,全0才為0
1010 1010 | 1111 0000 -------------------1111 1010特點(diǎn):和0相或 保持不變,和1相或置1
應(yīng)用場(chǎng)景:將固定位置1
案例:將1010 1010的第2、3位變成1,其他不變
1010 1010 | 0000 1100 -------------------1111 1010~:按位取反
語法:0變1,1變0
~ 1010 1010=0101 0101應(yīng)用場(chǎng)景:配合&|操作
^:按位異或 (重要)
語法:相同為0,不同為1
1010 1010 ^ 0000 1111 -------------------1010 0101特點(diǎn):和0異或保持不變,和1異或 取反
應(yīng)用場(chǎng)景:將固定的位 發(fā)生高低電頻翻轉(zhuǎn)
案例:將1010 1010的第0位發(fā)生翻轉(zhuǎn)(要將哪位翻轉(zhuǎn),就將它與1異或)
1010 1010 ^ 0000 0001 -------------------1010 1011<<:左移運(yùn)算符(左邊丟棄,右邊補(bǔ)0)
(將二進(jìn)制位向左移動(dòng))
注意:移動(dòng)的位數(shù)不要超過自身長(zhǎng)度
1010 1100 << 2(左移2位)
>>:右移運(yùn)算符
右移分為:邏輯右移和算術(shù)右移
邏輯右移:右邊丟棄,右邊補(bǔ)0
算術(shù)右移:
①無符號(hào)數(shù):右邊丟棄,左邊補(bǔ)0
②有符號(hào)數(shù):
<1>正數(shù):右邊丟棄,左邊補(bǔ)0
<2>負(fù)數(shù):右邊丟棄,左邊補(bǔ)1
右移基本上是右邊丟棄,左邊補(bǔ)0
只有負(fù)數(shù)且算術(shù)右移,才會(huì)左邊補(bǔ)1
邏輯右移和算術(shù)右移是編譯器決定,但是我們可以檢測(cè)。
作業(yè):自己寫代碼,判斷你的編譯器是邏輯右移還是算術(shù)右移
char ch=0x85; // 1000 0101>>4//邏輯右移:1000 0101>>4 == 0000 1000 ==0x08//算術(shù)右移:1000 0101>>4 == 1111 1000 ==0xf8ch=ch>>4;printf("ch=%#x\n",ch);//0xf8是算術(shù)右移//邏輯右移、算術(shù)右移是編譯器決定的,我們只能測(cè)試,不能改變綜合案例:將data第1,5位清零(按位與),3、4位置1,其他位保持不變★
unsigned char data=0xaa; //1010 1010
//將data第1,5位清零
data = data & 1101 1101;// 與 完之后要賦值為data,才能更新它的值
1101 1101= ~(0010 0010)取反= ~(0010 0000 | 0000 0010)
0010 0000= 0000 0001 <<5
0000 0010= 0000 0001 <<1
所以:1101 1101= ~(0x01 <<5 | 0x01<<1)
data=data & ~(0x01<<5 | 0x01 <<1);//很清楚的能看出是第一位和第五位清零
第3、4位 置1
data=data | 0001 1000;
0001 1000 = 0001 0000 | 0000 1000=0x01<<4 | 0x01<<3
data = data | (0x01<<4 | 0x01<<3);
規(guī)律:只有按位與有取反,清零就 與、取反,后面第幾位就寫左移第幾位;要置1,只寫或,不寫取反,里面第幾位,就寫左移第幾位,每一位用或或上
知識(shí)點(diǎn)4【三目運(yùn)算符】?:
表達(dá)式1 ? 值1:值2
語法:如果表達(dá)式1為真,那么整個(gè)表達(dá)式的值為“值1”,反之為“值2”
案例
int ret=0;//最好先初始化再去賦值ret=3>2 ? 5:6;printf("ret=%d\n",ret);//ret=5知識(shí)點(diǎn)5【逗號(hào)運(yùn)算符】
案例:逗號(hào)運(yùn)算符
int data1=0;int data2=0;//賦值運(yùn)算符和逗號(hào)運(yùn)算符,逗號(hào)運(yùn)算符優(yōu)先級(jí)其實(shí)是最低的data1=3,4,5,6;//先執(zhí)行data1=3data2=(3,4,5,6);//小括號(hào)優(yōu)先級(jí)最高,逗號(hào)運(yùn)算符結(jié)合性是從左往右,所以data2=6printf("data1=%d\n",data1);//3printf("data2=%d\n",data2);//6
知識(shí)點(diǎn)6【符合運(yùn)算符】
+= 、 -= 、 = 、 /= 、%= 等等
a+=b ===》a=a+b
a * =b ===》a= a * b
注意:等號(hào)的右邊必須看成一個(gè)整體
案例
int data = 3;//將等號(hào)右邊看成一個(gè)整體data *= 3+5;//data=data * (3+5);printf("data=%d\n",data);//24知識(shí)點(diǎn)7【自增自減 運(yùn)算符】
++i 或者 --i :先加、減 ,后使用
i++或者i–:先使用,后加、減
注意:i++或者++i作為單獨(dú)的指令,是沒有區(qū)別的
知識(shí)點(diǎn)7【優(yōu)先級(jí)】分析已有的代碼
優(yōu)先級(jí)高的先執(zhí)行,同級(jí)別的優(yōu)先級(jí)要看結(jié)合性
C語言運(yùn)算符的優(yōu)先級(jí)
自己寫代碼,盡量加小括號(hào)
知識(shí)點(diǎn)8【if 語句】
1、如果只在乎項(xiàng)目的一個(gè)結(jié)果,選擇if
if(表達(dá)式)
{
????語句1;
}
表達(dá)式為真,才會(huì)執(zhí)行語句1;
2、如果項(xiàng)目只有兩種結(jié)果,且不會(huì)同時(shí)出現(xiàn)。請(qǐng)選擇if…else…
if(表達(dá)式)
{
????語句1;
}
else
{
????語句2;
}
表達(dá)式為真執(zhí)行語句1,否則執(zhí)行語句2
3、如果一個(gè)項(xiàng)目 有多個(gè)結(jié)果 且不同時(shí)出現(xiàn)。選擇if…else if…else if…else
if(表達(dá)式1)
{
????語句1;
}
else if(表達(dá)式2) //if后面要加表達(dá)式
{
????語句2;
}
else //可以省略
{
????語句n;
}
只有表達(dá)式1位真,執(zhí)行語句1,;只有表達(dá)式2位真,執(zhí)行語句2;所有表達(dá)式都為假,才執(zhí)行語句n。
注意:只有前面的條件不滿足,才會(huì)判斷后面的條件,如果前面的條件滿足,后面的條件不管真假都不會(huì)執(zhí)行。
4、一個(gè)項(xiàng)目有多個(gè)結(jié)果,不確定是否同時(shí)出現(xiàn)
if(表達(dá)式1)
{
????語句1;
}
if(表達(dá)式2)
{
????語句2;
}
if(表達(dá)式3)
{
????語句3;
}
每個(gè)if語句都是獨(dú)立的。
作業(yè):鍵盤輸入一個(gè)數(shù),能否被3和7同時(shí)整除
知識(shí)點(diǎn)9【switch 選擇語句】
switch(表達(dá)式)
{
case 值1: // 不能是實(shí)型、字符串,只能是整型和字符(本質(zhì)是ASCII)
????????語句1;
????????break;
case 值2:
????????語句2;
????????break;
case 值3:
????????語句3;
????????break;
default: //可以省略
????????語句n;
????????break;
}
switch就是判斷表達(dá)式的值是否和值1,值2,值3相等,來找到接下來程序的進(jìn)入點(diǎn)。
int data=0;printf("請(qǐng)輸入一個(gè)int數(shù)據(jù):");scanf("%d",&data);//判斷data對(duì)3的余數(shù)(有0,1,2三種情況)switch(data%3){case 0:printf("余數(shù)為0\n");break;case 1:printf("余數(shù)為1\n");break;case 2:printf("余數(shù)為2\n");break;}案例:有時(shí)候break可以省略
void test23() {char ch=0;printf("請(qǐng)輸入你的方向:wasd\n");ch=getchar();switch(ch){case 'w':case 'W':printf("向上移動(dòng)\n");break;case 'a':case 'A':printf("向左移動(dòng)\n");break;case 's':case 'S':printf("向下移動(dòng)\n");break;case 'd':case 'D':printf("向右移動(dòng)\n");break;}}03_循環(huán)語句及數(shù)組
知識(shí)點(diǎn)1 【for循環(huán)】
for(初始語句; 循環(huán)條件 ; 步進(jìn)條件) {//循環(huán)語句 } //初始語句:只在循環(huán)開始時(shí)執(zhí)行一次 //循環(huán)條件:每次循環(huán)都要執(zhí)行,如果循環(huán)條件為真,進(jìn)入循環(huán)體 如果為假,退出循環(huán)體 //步進(jìn)條件:每次循環(huán)結(jié)束的時(shí)候要執(zhí)行的語句案例: 求1~100的和
//1~100的和 1+2+3+4+...+100int i =0;int sum=0;for(i=1;i<=100;i++)// i++ ==> i=i+1{sum=sum+1}printf("sum=%d\n",sum);案例:
//1~100的和 1+2+3+4+...+100int i =1;int sum=0;//如果變量提前初始化了,for循環(huán)的初始化語句可以省略for(;;)//建議不要這么做{//如果for省略循環(huán)條件,必須在循環(huán)語句中實(shí)現(xiàn)退出循環(huán)的條件if(i>100)break;//跳出循環(huán)sum=sum+i;i++;//如果for省略步進(jìn)條件,必須在循環(huán)語句中實(shí)現(xiàn)步進(jìn)動(dòng)作}printf("sum=%d\n",sum);案例:break只能跳出離它最近的一層循環(huán)
void test26(){for(;;){for(;;){break;//只能跳出離他最近的一層循環(huán)}}}continue
continue:結(jié)束本次循環(huán),立即從當(dāng)前位置直接進(jìn)入下一次循環(huán)
作業(yè):
1、求出1~100中能被7整除的數(shù)。
案例:求出0~100的所有偶數(shù)的和
//求0 2 4 6...100的和int i=0;int sum=0;for(;i<=100;i=i+2)//步進(jìn)條件不是單純的i++{if(i==50)continue;//結(jié)束本次循環(huán),立即從當(dāng)前位置直接進(jìn)入下一次循環(huán)sum+=i;}printf("sum=%d\n",sum);//2550break和continue的區(qū)別
break語句用于跳出本層循環(huán)
continue用于結(jié)束本次循環(huán)
循環(huán)嵌套循環(huán)
//外層循環(huán)的次數(shù) * 內(nèi)層循環(huán)的次數(shù) == 總循環(huán)次數(shù) void test28(){int i=0;int j=0;for(i=0;i<10;i++)// 0~9=10{for(j=0;j<10;j++)// 0~9=10{printf("i=%d,j=%d\n",i,j);//輸出幾次?100次}} }知識(shí)點(diǎn)2【while 循環(huán) 和 do…while 循環(huán)】
while(循環(huán)條件) {//循環(huán)語句 }//如果循環(huán)條件為真就進(jìn)入循環(huán)體執(zhí)行循環(huán)語句注意:
1、while沒有初始化語句 ,用戶要提前初始化
2、while沒有步進(jìn)語句, 用戶必須在循環(huán)語句中寫好步進(jìn)語句。
案例:
int i=1;int sum=0;//注意初始化while(i<=100)//1~100和{sum+=i;i++;}printf("sum=%d\n",sum);//5050
注意:局部變量如果不初始化,內(nèi)容不確定
do {//循環(huán)語句 }while(循環(huán)條件);
先執(zhí)行循環(huán)語句,在判斷循環(huán)條件是否滿足, 如果為真,進(jìn)行下一次循環(huán),如果為假,直接退出循環(huán)
案例
int num=0;do{printf("ok\n");}while(num>0);//先進(jìn)do再去判斷條件,所以會(huì)將ok打印出來知識(shí)點(diǎn)3【goto 跳轉(zhuǎn)】(慎用!)
void test31(){printf("---------001---------\n");printf("---------002---------\n");goto here;//注意這里是分號(hào)printf("---------003---------\n");printf("---------004---------\n");printf("---------005---------\n"); here://注意這里是冒號(hào)printf("---------006---------\n");printf("---------007---------\n"); }int main(int argc,char *argv[]){test31(); return 0; }
作業(yè):
重復(fù)輸入1~7的數(shù)字判斷星期幾,注意輸入0,就結(jié)束程序,如果是0或1 ~7以外的數(shù),請(qǐng)?zhí)崾尽罢?qǐng)重新輸入有效數(shù)值“
總結(jié):
for 和 while 我們?nèi)绾芜x擇呢?
for和while低位一樣
建議:
如果循環(huán)次數(shù)是確定的,建議選擇for。
如果循環(huán)次數(shù)不確定,只知道退出的條件,建議選擇while
知識(shí)點(diǎn)4【數(shù)組的概述】
知識(shí)點(diǎn)5【一維數(shù)值數(shù)組】
1、數(shù)組的定義
需求:請(qǐng)定義一個(gè)數(shù)組,該數(shù)組有十個(gè)元素,每個(gè)元素為int類型
在定義的時(shí)候:(按照步驟來,因?yàn)橐院蟮臄?shù)組很復(fù)雜)
a、arr[ ] arr和中括號(hào)結(jié)合時(shí)就是數(shù)組
b、將確定的元素的個(gè)數(shù)放入中括號(hào)中
c、用元素的類型定義一個(gè)普通變量
d、從上往下整體替換(變量名)
arr[10]
int num;
用arr[10]整體替換num——》int arr[10];
需求:請(qǐng)定義一個(gè)數(shù)組,該數(shù)組有十個(gè)元素,每個(gè)元素為地址,每個(gè)地址為int變量的地址。
arr[10]
*p //每個(gè)元素為地址,地址就是指針
int num;
//從上往下依次替換
arr[10]替換p——》 * arr[10]
星花 * arr [10]替換num——》int * arr [10]
注意:
1、數(shù)組名arr不能和其他變量名同名
2、數(shù)組的元素下標(biāo)是從0開始的:0~9
3、數(shù)組的元素分別是:arr[0]、arr[1]…arr[9],如果訪問arr[10]數(shù)組越界
4、數(shù)組的元素等價(jià)于普通變量
5、在定義數(shù)組的時(shí)候,中括號(hào)里面的值必須為常量,不能是變量。
案例1:遍歷數(shù)組
//局部數(shù)組(變量)如果不初始化,內(nèi)容也是不確定的int arr[10];//遍歷數(shù)組——》for循環(huán)int i=0;for(i=0;i<10;i++){printf("%d ",arr[i]);//輸出的都是不確定的值}printf("\n");案例2:數(shù)組的初始化
初始化:定義的時(shí)候給變量或者數(shù)組元素賦值的動(dòng)作,叫做初始化。
全部初始化:
int arr[5]={10,20,30,40,50}; //如果是全部初始化,數(shù)組元素的個(gè)數(shù)可以省略,實(shí)際元素個(gè)數(shù)由初始化個(gè)數(shù)決定 int arr[]={10,20,30,40,50};//少用//錯(cuò)誤演示: int arr[];//沒有初始化,不知道開辟多大空間部分初始化:
int arr[5]={10,20,30};//部分初始化,未被初始化的部分補(bǔ)0(重要)//初始化數(shù)字常見操作(將數(shù)組所有元素清零) int arr[5]={0};//初始化arr[0]=0,未被初始化部分自動(dòng)補(bǔ)0 int arr[5]={2};//2 0 0 0 0拓展:特殊初始化
//了解 int arr[5]={[2]=3,[4]=7}; // 0 0 3 0 7 //[2]=3 將數(shù)組的第二個(gè)元素 初始化為 3 //[4]=7 將數(shù)組的第四個(gè)元素 初始化為 72、數(shù)組的空間大小(重要)
//arr數(shù)組名 作為數(shù)組類型 代表的是數(shù)組空間的總大小int arr[5]={10,20,30,40,50};int n=0;printf("數(shù)組的總大小:%d\n",sizeof(arr));//20個(gè)字節(jié)//數(shù)組的總大小=元素的個(gè)數(shù)*每個(gè)元素的大小// 20 = 5 * 4//數(shù)組元素的大小 arr[0]是數(shù)組第0個(gè)元素,數(shù)組的每個(gè)元素都是相同類型printf("數(shù)組元素的大小=%d\n",sizeof(arr[0]));//4//數(shù)組元素的個(gè)數(shù)=數(shù)組的總大小 / 每個(gè)元素的大小n= sizeof(arr) / sizeof(arr[0]);printf("數(shù)組元素的個(gè)數(shù)為:%d\n",n)//5;遍歷數(shù)組
//arr數(shù)組名 作為數(shù)組類型 代表的是數(shù)組空間的總大小int arr[5]={10,20,30,40,50};int n= sizeof(arr) / sizeof(arr[0]);//是求數(shù)組的元素個(gè)數(shù)int i=0;//遍歷數(shù)組for(i=0;i<n;i++){printf("%d ",arr[i]);}printf("\n");案例:
int arr1[5]={1,2,3};int arr2[]={1,2,3};char arr3[5]={1,2,3};int arr4[]={[5]=7};//VC6.0不支持printf("%d\n",sizeof(arr1));//20printf("%d\n",sizeof(arr2));//12printf("%d\n",sizeof(arr3));//5printf("%d\n",sizeof(arr4));//6*4=243、數(shù)組元素的操作
數(shù)組元素等價(jià)于普通變量
int arr[5]={1,2,3,4,5};int n=sizeof(arr)/sizeof(arr[0]);int i=0;//給數(shù)組元素賦值arr[0]=100;//num++arr[1]++; //arr[1]=arr[1]+1;//scanf("%d",&num)scanf("%d",&arr[2]);for(i=0;i<n;i++){printf("%d ",arr[i]);}printf("\n");案例:定義一個(gè)數(shù)組 5個(gè)元素,每個(gè)元素int類型,獲取鍵盤輸入
//數(shù)值數(shù)組只能逐個(gè)元素操作 不能整體操作int arr[5]={0};int n=sizeof(arr)/sizeof(arr[0]);int i=0;printf("請(qǐng)輸入%d個(gè)int型數(shù)據(jù)\n",n);for(i=0;i<=n;i++){scanf("%d",&arr[i]);//中括號(hào)[]的優(yōu)先級(jí)高于&//&arr[i] 表示取第i個(gè)元素的地址}for(i=0;i<n;i++){printf("%d ",arr[i]);//arr[i]訪問數(shù)組的第i個(gè)元素 }作業(yè):定義一個(gè)數(shù)組 5個(gè)元素,每個(gè)元素int類型,獲取鍵盤輸入,請(qǐng)求出數(shù)組的最大值,最小值,平均值。
知識(shí)點(diǎn)6【二維數(shù)組】
1、二維數(shù)組的定義
二維數(shù)組也叫數(shù)組的數(shù)組。
二維數(shù)組的遍歷:
//先寫內(nèi)層循環(huán),再把它粘貼到外層循環(huán)中去 int i=0; for(i=0;i<3;i++) {//遍歷第i行int j=0;for(j=0;j<4;j++){printf("%d ",arr[i][j])} }案例:
#include<stdio.h> void test01() {int arr[3][4];//局部數(shù)組不初始化,內(nèi)容不確定int i=0,j=0;for(i=0;i<3;i++)//行的變化{//先寫內(nèi)層循環(huán),再寫外層循環(huán),將內(nèi)層循環(huán)復(fù)制到外層循環(huán)for(j=0;j<4;j++)//列的變化{printf("%d ",arr[i][j]);}printf("\n");} } int main(int argc,char *argv[]) {test01();return 0; }2、二維數(shù)組的初始化
分段初始化:用大括號(hào)里面的大括號(hào),明確的表示一行
int arr[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};連續(xù)初始化:放滿一行才能放下一行
int arr[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};案例:
int arr1[3][4]={{1,2},{3},{4,5}};int arr2[3][4]={1,2,3,4,5};04_數(shù)組與函數(shù)
知識(shí)點(diǎn)1 【作業(yè)講解】
作業(yè):定義int arr[3][4]的二維數(shù)組,獲取鍵盤輸入,并求出每一行的平均值。
//作業(yè):定義int arr[3][4]的二維數(shù)組,獲取鍵盤輸入,并求出每一行的平均值。 void test03() {int arr[3][4]={0};//將整個(gè)數(shù)組初始化為0//獲取鍵盤輸入int i=0,j=0;for(i=0;i<3;i++){for(j=0;j<4;j++){scanf("%d",&arr[i][j]);}}for(i=0;i<3;i++){//求每一行的平均值float sum=0; for(j=0;j<4;j++){sum+= arr[i][j];}printf("第%d行的平均值為%.2f\n",i,sum/4.0);}運(yùn)行結(jié)果:
案例:求每一列的平均值
void test03() {int arr[3][4]={0};//將整個(gè)數(shù)組初始化為0//獲取鍵盤輸入int i=0,j=0;for(i=0;i<3;i++){for(j=0;j<4;j++){scanf("%d",&arr[i][j]);}}for(i=0;i<3;i++){//求每一行的平均值float sum=0; for(j=0;j<4;j++){sum+= arr[i][j];}printf("第%d行的平均值為%.2f\n",i,sum/4.0);}for(j=0;j<4;j++){int sum=0;for(i=0;i<3;i++){sum+=arr[i][j];}printf("第%d列的平均值為%d\n",j,sum/3);}// 計(jì)算第0列}int main(int argc,char *argv[]) {test03();return 0; }
知識(shí)點(diǎn)2 【字符數(shù)組】(重要)
字符數(shù)組:本質(zhì)是數(shù)組,只是數(shù)組的美國(guó)元素是字符。
//定義一個(gè)數(shù)組有五個(gè)元素,每個(gè)元素為char
arr[5]
char ch;
從上往下替換======>
char arr[5];
字符數(shù)組的初始化
//初始化:逐個(gè)字符初始化(不推薦) char str[6]={'h','e','l','l','o'}; //str[0]== 'h'的ASCII碼值//初始化:以字符串的形式初始化(推薦) char str[6]="hello";//初始化更加簡(jiǎn)潔字符數(shù)組的遍歷
char str[6]="hello";//逐個(gè)字符遍歷(不推薦)int i=0;for(i=0;i<6;i++){printf("%c",str[i]);}printf("\n---------\n");//字符數(shù)組可以整體遍歷(推薦)printf("%s\n",str);//%s: 從給定字符串的首元素地址開始逐個(gè)字符遍歷,直到遇到\0結(jié)束//%s加數(shù)組名str運(yùn)行結(jié)果:
%s:只要告訴字符串第0個(gè)元素的地址,那么就可以逐個(gè)元素打印,直到遇到\0結(jié)束
非常重要:一維數(shù)組名代表的是 數(shù)組第0個(gè)元素的地址。(必須記住)
char str[6]="hello";//%p是十六進(jìn)制輸出地址printf("第0個(gè)元素的地址:%p\n",&str[0]);printf("數(shù)組名:%p\n",str);逐個(gè)字符初始化和字符串初始化的區(qū)別
char str1[]={'h','e','h','e'};//逐個(gè)元素初始化,系統(tǒng)不會(huì)給它添加‘\0’char str2[]="hehe";//以字符串初始化,系統(tǒng)會(huì)給字符串添加'\0'//以上情況的前提條件是中括號(hào)里面沒給數(shù)組長(zhǎng)度//開辟的空間大小printf("sizeof(str1)=%d\n",sizeof(str1));//4printf("sizeof(str2)=%d\n",sizeof(str2));//5
數(shù)組中括號(hào)里面沒有給定元素的個(gè)數(shù)那么元素的實(shí)際個(gè)數(shù)由初始化情況決定
%s輸出的內(nèi)容
%s的作用是:從數(shù)組的第0個(gè)元素開始,逐個(gè)元素輸出,直到遇到\0結(jié)束
★★★運(yùn)行結(jié)果:
字符數(shù)組獲取鍵盤的字符串
定義一個(gè)字符數(shù)組,有足夠大的空間
char buf[128]="";printf("請(qǐng)輸入一個(gè)字符串\n");scanf("%s",buf);//不能獲取帶空格的字符printf("buf=%s\n",buf);運(yùn)行結(jié)果
scanf和%s使用的時(shí)候有個(gè)缺點(diǎn),遇到空格會(huì)結(jié)束輸入
解決方法:用gets()——》把鍵盤輸入的大小全搬給你
案例:
gets()缺點(diǎn):獲取鍵盤輸入的時(shí)候,不會(huì)管buf的大小,容易造成內(nèi)存污染
fgets():既可以獲取帶空格的字符串,也可以保證buf的不越界
#include<stdio.h> char *fgets(char *s, int size, FILE *stream) //s表示存放字符串的空間地址 //size表示能提取字符串的最大長(zhǎng)度 size-1(留一個(gè)給'\0') //stream stdin表示標(biāo)準(zhǔn)輸入設(shè)備 返回值:就是獲取到的字符串的首元素地址案例:
void test07() {char buf[10]="";printf("請(qǐng)輸入一個(gè)字符串\n");fgets(buf,sizeof(buf),stdin);printf("buf=%s\n",buf); }int main(int argc,char *argv[]) {test07();return 0; }
提高案例:字符串的大小寫的轉(zhuǎn)換
//'a' 97 'b' 98 'c'99 ~ 'z'122//'A' 65 'B' 66 'C'67 ~ 'Z'90//規(guī)律:小寫字母的ASCII值比大寫字母的ASCII值相差32//printf("%d %d\n",'a','z');//printf("%d %d\n",'A','Z');char ch='a';//小寫變大寫 -32ch=ch-32; //其實(shí)也可以寫:ch=ch-('a'-'A');printf("ch=%c\n",ch);//大寫變小寫 +32ch=ch+32;//其實(shí)也可以寫:ch=ch+('a'-'A');printf("ch=%c\n",ch);作業(yè):鍵盤獲取一個(gè)字符串,大小自定義,將字符串的大寫字母變小寫,小寫字母變大寫,其他符號(hào)保持不變
思路如下:
1、獲取一個(gè)字符串
2、用for循環(huán)將字符串的逐個(gè)字符進(jìn)行大小寫轉(zhuǎn)換
知識(shí)點(diǎn)3【二維字符數(shù)組】(了解)
一維字符數(shù)組是存放多個(gè)字符的
二維字符數(shù)組是存放多個(gè)字符串的 ,每個(gè)字符串占一行
//不管是數(shù)值還是字符的二維數(shù)組,在初始化的時(shí)候是庫(kù)省略行標(biāo)的,行數(shù)又具體初始化決定 char str[3][16]={"hehe","haha","heihei"};//要保證每個(gè)字符串小于16個(gè)字節(jié) str[0]="hehe"; str[1]="haha"; str[2]="heihei"; char str[3][16]={"hehe","haha","heihei"};//對(duì)整體字符串輸出,只需要使用行標(biāo)printf("%s\n",str[0]);//heheprintf("%s\n",str[1]);//hahaprintf("%s\n",str[2]);//heihei//輸出的是 字符串中某個(gè)字符 必須用行標(biāo)和列表printf("%c\n",str[1][3]);//a二維字符數(shù)組獲取鍵盤輸入的字符串:
應(yīng)用場(chǎng)景:當(dāng)鍵盤需要輸入多個(gè)獨(dú)立的字符串,用戶必須單獨(dú)存儲(chǔ)好,請(qǐng)選擇二維字符數(shù)組
輸入的字符串個(gè)數(shù),決定了二維數(shù)組的行數(shù) , 輸入字符串中最大長(zhǎng)度,決定了二維字符數(shù)組的列數(shù)。
//hehe haha xixi heihei char buf[4][16]={""};//二維字符數(shù)組初始化為0int i=0;//獲取鍵盤的字符串for(i=0;i<4;i++){scanf("%s",buf[i]);//buf[i]已經(jīng)代表是第i行的首元素地址,所以這時(shí)候不要取地址}//輸出鍵盤的字符串for(i=0;i<4;i++){printf("buf[%d]=%s\n",i,buf[i]);}
作業(yè):
1、鍵盤輸入十個(gè)int數(shù)據(jù),對(duì)其從小到大排序
2、鍵盤輸入一個(gè)字符串“abcdef”進(jìn)行前后的顛倒(逆置)——》“fedcba”
知識(shí)點(diǎn)4 【函數(shù)概述】
1、函數(shù)的定義:實(shí)現(xiàn)函數(shù)的功能,確定函數(shù)體、返回值、形參類型。讓函數(shù)存在
2、函數(shù)的聲明:不是實(shí)現(xiàn)函數(shù)功能,僅僅是說明函數(shù)該函數(shù)有返回值類型,形參類型,函數(shù)名。
3、函數(shù)的調(diào)用:函數(shù)的執(zhí)行
1、函數(shù)的定義
// 返回值類型:函數(shù)將來返回值的類型 //函數(shù)名:函數(shù)的入口地址 //形參類型:函數(shù)外部數(shù)據(jù) 傳遞到函數(shù)內(nèi)部的橋梁 //函數(shù)體:具體的函數(shù)功能代碼 返回值類型 函數(shù)名(形參類型 形參) {函數(shù)體; }2、函數(shù)的聲明
返回值類型 函數(shù)名(形參類型 形參);3、函數(shù)的調(diào)用
//函數(shù)外部的實(shí)際數(shù)據(jù) 函數(shù)名(實(shí)參);//沒有函數(shù)返回值類型案例:
#include<stdio.h> //函數(shù)聲明(必須在函數(shù)調(diào)用的前方聲明才有作用)//編譯器是從上往下執(zhí)行的 void my_fun();//函數(shù)聲明:告訴編譯器,該函數(shù)存在,請(qǐng)通過編譯。int main(int argc,char *argv[]) {//函數(shù)的調(diào)用:函數(shù)名+()my_fun();return 0; }//函數(shù)的定義 void my_fun() {printf("my fun\n");return;//void沒有返回值,return后面什么都不寫//return功能:1、返回函數(shù)結(jié)果 2、結(jié)束函數(shù) }可以省略函數(shù)聲明:函數(shù)的調(diào)用在函數(shù)定義的下方,就可以省略函數(shù)聲明
#include<stdio.h> //函數(shù)聲明(必須在函數(shù)調(diào)用的前方聲明才有作用)//編譯器是從上往下執(zhí)行的 //void my_fun();//函數(shù)聲明:告訴編譯器,該函數(shù)存在,請(qǐng)通過編譯。//函數(shù)的定義 void my_fun() {printf("my fun\n");return;//void沒有返回值,return后面什么都不寫 }int main(int argc,char *argv[]) {//函數(shù)的調(diào)用:函數(shù)名+()my_fun();return 0; }建議:
往往建議將主函數(shù)寫在上方,將函數(shù)定義寫在下方。(通過主函數(shù),一眼就能看出大致框架)
知識(shí)點(diǎn)5 【函數(shù)的參數(shù)】
1、如果函數(shù)的形參什么都不寫 在調(diào)用的時(shí)候可以傳實(shí)參,只是實(shí)參得不到使用
#include<stdio.h>void my_fun(10,20);int main(int argc,char *argv[]) {my_fun();return 0; }//如果函數(shù)的形參什么都不寫 在調(diào)用的時(shí)候可以傳實(shí)參,只是實(shí)參得不到使用 void my_fun() {printf("my fun\n");return; }2、如果函數(shù)沒有參數(shù),請(qǐng)將形參寫成void
#include<stdio.h>void my_fun(void);int main(int argc,char *argv[]) {//my_fun(10,20);//errormy_fun();return 0; }//如果函數(shù)的參數(shù)為void,在調(diào)用的時(shí)候就不要給函數(shù)傳遞實(shí)參 void my_fun(void) {printf("my fun\n");return; }3、函數(shù)參數(shù)的傳遞
總結(jié)
以上是生活随笔為你收集整理的逆向基础之C语言 第一篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: echarts 大屏可视化_看似复杂炫酷
- 下一篇: BUUCTF-Reverse:Simpl