C語言程序設(shè)計(jì)從入門到進(jìn)階【比特鵬哥c語言2023完整版視頻教程】(c語言基礎(chǔ)入

- 'a'

%d c/97 輸出字符打出97---就是輸出'c' 所對(duì)應(yīng)的ASCII碼值
字符串-字符數(shù)組 -和arr()的整型數(shù)組是有區(qū)別的。

這里在打印moth時(shí),用“month=%02d\n”其目的是,給month補(bǔ)零,計(jì)算機(jī)可能會(huì)自動(dòng)省略01,02前面的零。

fioat類型后面的0.0f 這個(gè)f的作用是,讓數(shù)據(jù)為float類型,如果不加,就算定義其為單精度浮點(diǎn)型,它也會(huì)占雙精度浮點(diǎn)型的空間。


%.3lf -----保留三位小數(shù)的雙精度浮點(diǎn)型。
%.2f ----作用是保留兩位小數(shù)

printf函數(shù)的返回值是 ,字符串的長度減一,減的一是\0,在返回值時(shí)這個(gè)并不算上。(也就是鍵盤打上去的字符數(shù))

\n 如何輸出 用\\n 和''的輸出。

do while循環(huán)

break----即整體終止、、
。
continue ---跳到循環(huán)的判斷語句。
goto語句
跳到我們想要的地方

-s 關(guān)機(jī) -t 設(shè)置時(shí)間關(guān)機(jī)
-a取消關(guān)機(jī)
*****函數(shù)
子程序
1 庫函數(shù)
2 自定義函數(shù).
庫函數(shù)(必須包含對(duì)應(yīng)的頭文件)
求字符串長度
比較2個(gè)字符串的大小
打印數(shù)據(jù)
。。。。。
查看庫函數(shù):www.cplusplus.com
strcpy :

memset 內(nèi)存設(shè)置 的用法


size-t 無符號(hào)整型
輸入時(shí)的小細(xì)節(jié)。
用自定義函數(shù)來求較大值。

用自定義函數(shù)交換兩個(gè)數(shù)的內(nèi)容。

交換就可以了,
不需要返回最后的內(nèi)容用 void 來修飾函數(shù)。
交換數(shù)字需要引入其他變量用來存放數(shù)據(jù)。

這函數(shù)為什么沒完成任務(wù):
x,y,a,b,是個(gè)四個(gè)不同的空間
a和b叫實(shí)參
專業(yè)術(shù)語:
*當(dāng)實(shí)參傳遞給形參的時(shí)候,形參是實(shí)參的一份臨時(shí)拷貝,對(duì)形參的修改不會(huì)影響實(shí)參。
形參需要用指針變量來,通過地址遠(yuǎn)程的進(jìn)行修改。
用指針變量來改數(shù)據(jù)。
舉例:

應(yīng)用到剛才的交換代碼:


*px ---就相當(dāng)于對(duì)地址的的解譯找到實(shí)參a的值,并進(jìn)行修改。
一個(gè)工程中可以有多個(gè).c文件但多個(gè).c文件只能有一個(gè)主函數(shù)。
在使用函數(shù)的時(shí)候,什么情況下不需要傳地址,什么情況下需要傳地址。
交換函數(shù) 重要的是空間;加和函數(shù)重要的是數(shù)據(jù)。

px py 不帶*交換地址后,,對(duì)a,b的數(shù)據(jù)交換結(jié)果不會(huì)改變
函數(shù)參數(shù)
實(shí)參:
可以是 常量,變量,表達(dá)式,函數(shù)等;
無論實(shí)參是何種形式的量,在進(jìn)行函數(shù)調(diào)用時(shí),他們必須有確定的值,一邊把這些值傳遞給形參。
形式參數(shù):
(其為參數(shù)創(chuàng)造的空間,只有被調(diào)用的時(shí)候才開辟,用完就銷毀,不占空間,)
形式參數(shù)是函數(shù)名后括號(hào)中的變量,因?yàn)樾问絽?shù),只有在函數(shù)調(diào)用的過程中才實(shí)例化。調(diào)用完成以后就自動(dòng)銷毀了。
當(dāng)實(shí)參傳遞給形參的時(shí)候,形參是實(shí)參的一份臨時(shí)拷貝。
函數(shù)的調(diào)用:
1,傳值調(diào)用;
2,傳址調(diào)用;

break 的功能不如 return

自定義函數(shù)的功能要實(shí)現(xiàn)的足夠單一,足夠簡潔,才可能被反復(fù)使用。

0
二分法來找下標(biāo) 下標(biāo)有0,所以把找不到設(shè)置為return -1
sz的位置不同,會(huì)使結(jié)果發(fā)生不一樣的變化
不要奢望再函數(shù)內(nèi)部計(jì)算,實(shí)參內(nèi)部的元素個(gè)數(shù)。函數(shù)內(nèi)的arr[] 是指針,但可以直接用。
數(shù)組傳參實(shí)際上傳遞的是數(shù)組首元素的地址
而不是整個(gè)參數(shù)。
所以函數(shù)內(nèi)部計(jì)算一個(gè)函數(shù)參數(shù)部分的數(shù)組元素個(gè)數(shù)是不靠譜的。

除了int 等內(nèi)置類型
c99 中引入了布爾類型 bool 一個(gè)字節(jié)
表示真假的變量
false 0
true 1
盡量不要使用全局變量,能不用就不用。
嵌套調(diào)用
函數(shù)是可以互相調(diào)用,函數(shù)的地位都是平等的。
鏈?zhǔn)皆L問:4321

return 返回的是打印字符的個(gè)數(shù)
void 定義的函數(shù)不需要返回值。

main的三個(gè)參數(shù) int char* char *
函數(shù)的聲明和定義。
聲明: 一般出現(xiàn)在函數(shù)的使用前,要先聲明后使用。 一般放在頭文件中。(也可能聲明但沒使用。)
自己定義的頭文件用 " "


在初學(xué)編程,把所有的代碼寫到一個(gè)文件中最方便。
但是,公司里不是這么寫的。
1,協(xié)作的角度
2,模塊化
函數(shù)的聲明放頭文件
函數(shù)的內(nèi)容放到一個(gè)源文件
在另一個(gè)源文件使用時(shí) 引用其頭文件
在簡單的代碼里,即使不引用不聲明也是可以引用的,但不安全,工作中為保證自己的數(shù)據(jù)庫安全,是需要的。
導(dǎo)入靜態(tài)庫的方法

add.h 放聲明 可以了解到代碼的用法,
add.c 變二進(jìn)制靜態(tài)庫,保護(hù)自己的代碼
使用時(shí) 引用頭文件 按自己需求使用。
****函數(shù)遞歸
程序調(diào)用自身的編程技巧
把大事化小。

接受一個(gè)整型值,按順序打印他的每一位。
%d 打印有符號(hào)的整數(shù)
%u 打印無符號(hào)的整數(shù)
遞歸的實(shí)現(xiàn) 函數(shù)自己調(diào)用自己

函數(shù)隨著執(zhí)行數(shù)據(jù) 一步步向外執(zhí)行,得先執(zhí)行內(nèi)部的。這個(gè)過程叫遞歸。
需要判斷條件 終止遞歸 死遞歸會(huì)導(dǎo)致程序崩潰。
兩個(gè)條件:
需要限制條件,滿足這個(gè)限制條件的時(shí)候,遞歸不在繼續(xù)。
每次遞歸調(diào)用后越來越接近這個(gè)限制條件。
棧區(qū) 堆區(qū) 靜態(tài)區(qū)
第二個(gè)遞歸練習(xí)
參數(shù)部分寫成數(shù)組的形式
參數(shù)部分寫成指針的形式
參數(shù)是指針的形式?指的是第一個(gè)字母的空間。
str+1 取得是abc中b的地址。
用while實(shí)現(xiàn):

不創(chuàng)建臨時(shí)變量
遞歸的方式實(shí)現(xiàn):

遞歸與迭代
遞歸法求階乘

遞歸的層次太深會(huì)出現(xiàn),棧溢出的現(xiàn)象。
所以要使用效率高的方法。
迭代法

兩道趣味題

= 就是賦值 不能判斷
esle 和最近的一個(gè)沒匹配的if 匹配
switch語句,,分支內(nèi)的情況可以隨意調(diào)換
case 后的表達(dá)式只能是整型常量表達(dá)式
必須要用break才能跳出 接下來的表達(dá)式才不會(huì)執(zhí)行。
沒有初始化數(shù)組的元素個(gè)數(shù),就會(huì)根據(jù)初始化的內(nèi)容來推算元素個(gè)數(shù)。

一個(gè)逗號(hào)表達(dá)式是一個(gè)參數(shù):
誰申請(qǐng)的資源誰釋放。

在不同的函數(shù)內(nèi)使用相同的變量是可以的。

內(nèi)存的存儲(chǔ)(目前了解)
在函數(shù)內(nèi)復(fù)合語句創(chuàng)建的變量出了()就不能繼續(xù)使用了

return 無法同時(shí)返回兩個(gè)數(shù) 。
******
數(shù)組傳參 傳的是指針
arr【0】 -----*(arr+0);

形參用兩個(gè)指針
a,b 在兩個(gè)位置上都能用。傳參

用全局變量不傳參

函數(shù)不能嵌套定義
函數(shù)的實(shí)際參數(shù)和形式參數(shù)可以相同。
數(shù)組
1,數(shù)組的創(chuàng)建,
數(shù)組:一組相同類型元素的集合
int arra[10]
char ch[5]
double date[20]/date[15=5]
int arr[n]
括號(hào)內(nèi)的可以是變量-----C99后有這個(gè)標(biāo)準(zhǔn)是
為了支持變長數(shù)組
gcc test.c -std=C99
數(shù)組的初始化:
int arr[10]={1,2,3}; 不完全初始化 直接補(bǔ)0

char ch【10】={a,b,c} 依舊補(bǔ)0,但是是字符零 有帶有\(zhòng)0。
//abc0000000
char ch【10】=“abc”;
//abc\00000000
char ch【】=“abc”; 4個(gè)字符
char ch【】={'a','b','c' } 3個(gè)字符

一維數(shù)組的使用
數(shù)組的訪問原理
【】 下標(biāo)引用操作符
打印數(shù)組每個(gè)元素的地址。


線程是4線程,地址是連續(xù)的。
數(shù)組在內(nèi)存是連續(xù)存放的。
二維數(shù)組的創(chuàng)建及初始化
int arr[3][4]={1,2,3,4,2,3,4,5,3,4,5,6};
{{1,2},{3,4},{5,6}}
如果不完全初始化:默認(rèn)補(bǔ)0
///三行四列的數(shù)組即使分組后不夠的直接補(bǔ)0
char arr【5】【10】
二維數(shù)組和一維數(shù)組不同的是初始化時(shí)可以省略第一個(gè)括號(hào),也就是行,但不能省略列數(shù)。
二維數(shù)組的行列都是進(jìn)行編號(hào)的。

打印

二維數(shù)組也是通過下標(biāo)來訪問的?!尽肯聵?biāo)訪問符
可以把二維數(shù)組理解為一維數(shù)組的數(shù)組

二維數(shù)組在內(nèi)存中的存儲(chǔ)

二維數(shù)組在內(nèi)存中也是連續(xù)存放的。







數(shù)組越界
越界之后,編譯器是不報(bào)錯(cuò)的。

二維數(shù)組的行和列也會(huì)出現(xiàn)越界行為。
數(shù)組傳參的時(shí)候,形參有2種寫法:
1,數(shù)組
2,指針
形參是數(shù)組的形式 arr【】 括號(hào)也是必須的 直觀的形式
冒泡排序;
兩個(gè)相鄰的元素進(jìn)行比較, 需要升序

一趟冒泡排序讓一個(gè)數(shù)據(jù)來到它最終應(yīng)該出現(xiàn)的位置上

數(shù)組名
數(shù)組名本質(zhì)上是數(shù)組首元素的地址

數(shù)組名的字節(jié)

數(shù)組名嫩表示是首元素的地址
但有兩個(gè)例外
1,sizeof(數(shù)組名),這里的數(shù)組名表示整個(gè)數(shù)組的大小,單位是字節(jié)
2,&數(shù)組名,這里的數(shù)組名表示整個(gè)數(shù)組的地址,取出的也是整個(gè)數(shù)組的地址。

數(shù)組的地址和數(shù)組首元素的的地址一模一樣但是內(nèi)部范圍差別巨大。
二維數(shù)組的數(shù)組名
也表示數(shù)組首元素的地址。是第1行的地址
arr+1
表示第2行的地址,這是和一維數(shù)組的不同點(diǎn)
計(jì)算行的大小/列的大小

遞歸作業(yè)

字符交換
1,

strlen 求字符串長度不包含/0


在函數(shù)內(nèi),數(shù)組的形參arr,表示首元素的地址,但加上[ ] 這個(gè)下標(biāo)標(biāo)識(shí)符可以 表示數(shù)組內(nèi)參數(shù)的真實(shí)信息,并進(jìn)行修改。
c選項(xiàng)容易越界訪問

a[2][3] 兩個(gè)元素 3個(gè)子元素
int [10] 的內(nèi)存大小是40. int[5] 40

sizeof ---是一個(gè)操作符
是用來計(jì)算變量(類型)所占空間的大小,不關(guān)注存放的內(nèi)容。
strlen
是一個(gè)庫函數(shù),是專門求字符串長度的,只能針對(duì)字符串。
從參數(shù)給定的地址向后一直找\0,統(tǒng)計(jì)之前出現(xiàn)的字符的個(gè)數(shù)。

變長數(shù)組的舉例

操作符
算數(shù)操作符
/ ------整形的除法
-------浮點(diǎn)型的除法,兩端至少有一個(gè), 浮點(diǎn)型
% 取模操作符 -----兩端必須是整數(shù)。
移位操作符 移動(dòng)的是二進(jìn)制位。
操作的位數(shù) 不能移負(fù)數(shù)。
這是未定義 的輸入會(huì)報(bào)錯(cuò)。
a<<1 a自身是不發(fā)生改變的 就像計(jì)算操作符,,不給自己賦值,但計(jì)算的結(jié)果可以賦予其他值。
<< 左移操作符
左邊丟棄 右邊補(bǔ)零。
>> 右移操作符
整數(shù)的二進(jìn)制表示有三種
原碼
反碼
補(bǔ)碼
正整數(shù) 三碼相同

負(fù)整數(shù) 三碼是需要計(jì)算的.
原碼----符號(hào)位不變,其它位按位取反-----反碼
反碼----反碼加1-------補(bǔ)碼

整數(shù)在內(nèi)存中存的是 二進(jìn)制的補(bǔ)碼。
移位 移的是二進(jìn)制補(bǔ)碼。
負(fù)整數(shù)的移位結(jié)果需要補(bǔ)碼---反碼---原碼
一步步計(jì)算出來。

整數(shù)在左移操作符的結(jié)果是 無論正負(fù)*2.
左移,右移操作符 只能對(duì)正整數(shù)。
右移操作符
算術(shù)移位:右邊丟棄,左邊補(bǔ)原符號(hào)位。
邏輯移位:右邊丟棄,左邊補(bǔ)0
算術(shù)還是邏輯右移 取決于編譯器。
算術(shù)移位 絕大多數(shù)編譯器。
位操作符 ----也只適用于操作符
& - 按二進(jìn)制位 與
方法

計(jì)算出的是補(bǔ)碼
| - 按二進(jìn)制位 或

補(bǔ)碼的第一位是 1的話 需要計(jì)算其原碼,在進(jìn)行 算出其整數(shù)。
^ - 按二進(jìn)制位 異或 相同為0 相異則為1
- 不創(chuàng)建臨時(shí)變量實(shí)現(xiàn)實(shí)參之間的交換。

加合法 交換的結(jié)果可能會(huì)溢出
異或法

a^a=0
0^a=a
3^5^3=5 ----異或操作符支持交換律
- 賦值操作符
賦值是一個(gè)等號(hào)
a=x=y+1 連續(xù)賦值 不建議這樣寫
復(fù)合賦值符
a +=5 加五賦值給自己
a>>=1 右移賦值給自己
- 單目操作符
! 改變真假
— 改變正負(fù)號(hào)
+ 沒作用
& 取地址 取得是起始地址
p=&a --p就是指針
int* p=&a
sizeof 操作符--計(jì)算的是變量所占內(nèi)存空間的的大小。
單位是字節(jié)
計(jì)算類型所創(chuàng)建的變量所占空間的大小。
計(jì)算整個(gè)數(shù)組的大小。
~ 按位取反(二進(jìn)制位)
補(bǔ)碼到反碼 減一

| 按位或

按位與的用法


綜合運(yùn)用可以改 一長條二進(jìn)制的0和1
++a
--a

在函數(shù)中用(i++)也是先使用再+1
使用的延申
p 是指針變量時(shí) int* 是p的數(shù)據(jù)類型
()強(qiáng)制類型轉(zhuǎn)換
sizeof 是操作符不是函數(shù)
strlen 是庫函數(shù),是用來求字符串長度的。
字符類型的指針 ,也是4/8個(gè)字節(jié)
表示該指針?biāo)臻g內(nèi)放的是字符。
- 關(guān)系操作符
不是所有的數(shù)據(jù)都可以比較的
比如字符串之間的比較
“asd”==“rgfrc”//這樣寫是比較兩個(gè)字符串首元素的地址
- 邏輯操作符
&& 邏輯與操作符 都為真
左邊為假,右邊就不計(jì)算了
|| 邏輯或 只用一個(gè)為真
左邊為真,右邊就不計(jì)算了
a=0
i = a++&&++b&&d++ 就算第一個(gè)表達(dá)式
i = 這個(gè)賦值表達(dá)式優(yōu)先級(jí)最低 先算那兩個(gè)邏輯表達(dá)式。
當(dāng) a=1是 2 3 3 5 i=1
三目操作符;
條件操作符
()?():();
為真算第二個(gè) //為假算第三個(gè)
- 逗號(hào)表達(dá)式
從左到右以此計(jì)算,整個(gè)表達(dá)式的結(jié)果是最后一個(gè)表達(dá)式的結(jié)果

逗號(hào)表達(dá)式的應(yīng)用。
- 下標(biāo)引用
arr【3】 【】 -----下標(biāo)引用操作符
操作數(shù)arr 3
3【arr】 這樣寫結(jié)果一樣
數(shù)組是從零開始的7表示第八個(gè)元素 arr【7】arr表示首元素地址arr+1表示第二個(gè)
arr+7 表示第八個(gè)元素的地址
*(arr+7)=*(7+arr) 解引用
函數(shù)調(diào)用操作符
() -----操作符

結(jié)構(gòu)體調(diào)用操作符

- 表達(dá)式求值
1 ,關(guān)注優(yōu)先級(jí),結(jié)合性
2,隱形類型轉(zhuǎn)換
整型提升:


a+b時(shí)進(jìn)行整形提升

打印c時(shí)-------又要整型提升

整型提升后參與運(yùn)算 所占空間將變成4個(gè)字節(jié)

建議以后寫代碼 的運(yùn)算唯一性
c+ --c 問題表達(dá)式
數(shù)字的顯示都是原碼,但儲(chǔ)存都是以補(bǔ)碼的形式,計(jì)算和操作都是以以補(bǔ)碼的形式。
- 指針
指針是內(nèi)存中最小單元的編號(hào)稱為地址,地址就是編號(hào)。
本質(zhì)上 指針就是地址
口語中的指針 是指針變量,指針變量是用來存放地址的。
&a 取得地址是a首個(gè)地址
指針變量是用來存放地址的,地址是唯一標(biāo)識(shí)一塊地址空間的。
指針的大小是在32位的平臺(tái)是4 個(gè)字節(jié) X86
在64位是8個(gè)字節(jié) X64
NULL 指針的0值
sizeof 無符號(hào)整型 計(jì)算空間 操作符
- 指針類型
0x11223344 整數(shù)一共4個(gè)字節(jié)
11 一個(gè)字節(jié) 22 一個(gè)字節(jié)
33 一個(gè)字節(jié) 44 一個(gè)字節(jié)
指針類型
決定了指針在解引用的時(shí)候訪問幾個(gè)字節(jié)
int* 解引用時(shí)訪問4個(gè)字節(jié)
char* 解引用時(shí)訪問1個(gè)字節(jié)

指針類型:決定了指針+-1操作時(shí),跳過幾個(gè)字節(jié)
決定了了跳過的長度。
int* 和 float* 不能通用

- 野指針
p 沒有初始化 意味著沒有明確的指向。
一個(gè)局部變量不初始化,放的是隨機(jī)值
*p 就是非法訪問
這里的p就是野指針

指針的越界訪問也會(huì)造成野指針的問題
空指針 int* p=NILL
*p=100 會(huì)系統(tǒng)崩潰 寫如何調(diào)用沖突
使用指針時(shí)

野指針很危險(xiǎn)
野指針的成因:指針未初始化。
int* p=NULL 就是把它控制住了
要加一個(gè)判斷來 看p的指向是否有效
*p++ *p所指的參數(shù)不動(dòng)
a=*p,p++ *p的地址+1 指向下一個(gè)參數(shù)
(*p) ++ 這里是*p指向的參數(shù)+1
a=*p a++
指針和指針的相減,得到指針和指針之間的元素個(gè)數(shù)
不是所有的指針都能相減
指向同一片,空間的2個(gè)指針才能相減。
二級(jí)指針:

ppa 是pa的指針 pa是a的指針。
2級(jí)指針是用來存放一級(jí)指針變量的數(shù)組

指針數(shù)組
存放指針的數(shù)組就是指針數(shù)組。

數(shù)組指針的應(yīng)用
用一維數(shù)組 實(shí)現(xiàn)二維數(shù)組的訪問。

【】 就是解引用
結(jié)構(gòu)體
聲明:的結(jié)構(gòu)體類型。

p1 p2 是兩個(gè)全局變量
結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。結(jié)構(gòu)的沒個(gè)成員可以是不同類型的變量。

此時(shí)的p1 是局部變量。
結(jié)構(gòu)體變量的創(chuàng)建。

結(jié)構(gòu)體變量的初始化

含有結(jié)構(gòu)體的 結(jié)構(gòu)體初始化。


浮點(diǎn)數(shù)在內(nèi)存中不能精確保存。
結(jié)構(gòu)體的打印。

結(jié)構(gòu)體變量的成員。
用 . 操作符
也可在函數(shù)中用 -> 箭頭操作符

p 是把結(jié)構(gòu)體變量傳到形參
結(jié)構(gòu)體變量.成員變量。
sp 是把指針傳到形參,
結(jié)構(gòu)體指針-》 成員變量。
結(jié)構(gòu)體傳參
在介紹,在傳參時(shí),傳指針的優(yōu)越性。所創(chuàng)空間 小